Skip to content

Instantly share code, notes, and snippets.

@smeschke
Created December 29, 2018 00:24
Show Gist options
  • Save smeschke/b6ff8ba5a8f044d7a7475dfdb111d921 to your computer and use it in GitHub Desktop.
Save smeschke/b6ff8ba5a8f044d7a7475dfdb111d921 to your computer and use it in GitHub Desktop.
Warps an image to make it look like you didn't eat too much sweets
import cv2, numpy as np
# Read image
img = cv2.imread('/home/stephen/Desktop/vids/me.png')
h,w,_ = img.shape
sf = 1
img = cv2.resize(img, (int(w/sf), int(h/sf)))
img_pristine = img.copy()
# Get clicks from user
global click_list
click_list = []
def callback(event, x, y, flags, param):
if event == 1:
click_list.append((x,y))
print(x,y)
cv2.namedWindow('img')
cv2.setMouseCallback('img', callback)
# Takes an image and three points
# Returns an image where everythign is blacked out except that triangle
def get_mask(p0, p1, p2):
h,w,_ = img.shape
mask = np.zeros((h,w), np.uint8)
pts = np.array([p0,p1,p2], np.int32)
mask = cv2.drawContours(mask, [pts], 0, 255, -1)
return mask
# Take the image and two sets of points.
# Transform the image
def transform(img, p0, p1, old_center, new_center):
rows,cols,ch = img.shape
pts1 = np.float32([p0,p1,old_center])
pts2 = np.float32([p0,p1,new_center])
M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(img,M,(cols,rows))
return dst
# Takes an image, and a mask
# Returns the image, minus the parts of the image that are masked out
def mask_image(img, mask):
res = cv2.bitwise_and(img,img, mask= mask)
return res
k=0
while k!=27:
img_pristine = img.copy()
# Get the input from the user
while True:
# Display the input to the user
img_copy = img.copy()
try:
cv2.circle(img_copy, click_list[0], 12, 234)
cv2.line(img_copy, click_list[0], click_list[1], 255, 3)
cv2.circle(img_copy, click_list[1], 12, 234)
cv2.line(img_copy, click_list[1], click_list[2], 255, 3)
cv2.circle(img_copy, click_list[2], 12, 234)
cv2.line(img_copy, click_list[2], click_list[0], 255, 3)
cv2.circle(img_copy, click_list[3], 12, 234)
cv2.line(img_copy, click_list[3], click_list[2], 255, 3)
cv2.line(img_copy, click_list[3], click_list[1], 255, 3)
cv2.line(img_copy, click_list[3], click_list[0], 255, 3)
except: pass
# Check if all the input has been collected
if len(click_list)==5: break
# Show the image
cv2.imshow('img', img_copy)
k = cv2.waitKey(1)
if k == 27:break
# All of the user input has been collected, time to warp the image.
# A triangular region of the image is warped from this old center
old_center = click_list[3]
# To a new center
new_center = click_list[4]
# Define the three triangles
triangles = []
triangles.append((click_list[0], click_list[1]))
triangles.append((click_list[1], click_list[2]))
triangles.append((click_list[2], click_list[0]))
for a,b in triangles:
# Warp triangle
warped_triangle = transform(img_pristine, a, b, old_center, new_center)
# Generate mask of warped triangle
mask = get_mask(a, b, new_center)
# Mask source image (now the background)
background = mask_image(img, 255-mask)
#cv2.imshow('img', background)
#k = cv2.waitKey(0)
# Mask warped triangle image (new the foreground)
foreground = mask_image(warped_triangle, mask)
#cv2.imshow('img', foreground)
#k = cv2.waitKey(0)
# Paste warped triangle onto masked source
img = background + foreground
#cv2.imshow('img', img)
#k = cv2.waitKey(0)
cv2.imshow('img', img)
k = cv2.waitKey(0)
click_list = []
cv2.destroyAllWindows()
@smeschke
Copy link
Author

This file is used to warp images. First, two sets of three triangles are manually defined by the user. Then the first set of three triangles (the fat set) is morphed into the second set of triangles (the thin set).
triangle
warped

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment