#encoding = 'utf-8'
import numpy as np
import cv2
import math
def cross_point(line1,line2):
k1, b1 = calc_kb(line1)
k2, b2 = calc_kb(line2)
#print('res:',(k1,k2,b1,b2))
if k2 is None:
x = line2[0]
else:
x=(b2-b1)*1.0/(k1-k2)
y=k1*x*1.0+b1*1.0
return int(x),int(y)
def calc_kb(line):
x1=line[0]
y1=line[1]
x2=line[2]
y2=line[3]
if (x2-x1)==0:
k=None
b=0
else:
k=(y2-y1)*1.0/(x2-x1)
b=y1*1.0-x1*k*1.0
return k,b
def point_to_point(p1, p2):
return np.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
def CalcEuclideanDistance(point1, point2):
vec1 = np.array(point1)
vec2 = np.array(point2)
distance = np.linalg.norm(vec1 - vec2)
return distance
def CalcFourthPoint(point1, point2, point3):
D = (point1[0] + point2[0] - point3[0], point1[1] + point2[1] - point3[1])
return D
def adjust(polys):
list0 = polys.reshape((4, 2)).astype(np.int32)
list0 = list0[list0[:, 0].argsort()]
list1 = list0[0:2, :]
list2 = list0[2:4, :]
list1 = list1[list1[:, 1].argsort()]
list2 = list2[list2[:, 1].argsort()]
x1 = list1[0][0]
y1 = list1[0][1]
x4 = list1[1][0]
y4 = list1[1][1]
x2 = list2[0][0]
y2 = list2[0][1]
x3 = list2[1][0]
y3 = list2[1][1]
L2_left = CalcEuclideanDistance([x1, y1], [x4, y4])
L2_right = CalcEuclideanDistance([x2, y2], [x3, y3])
left_based = True if L2_left > L2_right else False
if left_based:
if x2 > x3:
[x3, y3] = CalcFourthPoint([x4, y4], [x2, y2], [x1, y1])
else:
[x2, y2] = CalcFourthPoint([x1, y1], [x3, y3], [x4, y4])
else:
if x1 < x4:
[x4, y4] = CalcFourthPoint([x3, y3], [x1, y1], [x2, y2])
else:
[x1, y1] = CalcFourthPoint([x2, y2], [x4, y4], [x3, y3])
#return np.array([[x1, y1], [x2, y2], [x3, y3], [x4, y4]])
return [[x1, y1], [x2, y2], [x3, y3], [x4, y4]]
def perspective_transformation(img, box):
pts1 = np.float32([box[0], box[1], box[3], box[2]])
widthA = np.sqrt(((box[1][0] - box[0][0]) ** 2) + ((box[1][1] - box[0][1]) ** 2))
widthB = np.sqrt(((box[3][0] - box[2][0]) ** 2) + ((box[3][1] - box[2][1]) ** 2))
heightA = np.sqrt(((box[3][0] - box[0][0]) ** 2) + ((box[3][1] - box[0][1]) ** 2))
heightB = np.sqrt(((box[2][0] - box[1][0]) ** 2) + ((box[2][1] - box[1][1]) ** 2))
max_width = max(int(widthA), int(widthB))
#max_width = 260
max_height = max(int(heightA), int(heightB))
#max_height = 390
pts2 = np.float32([[0, 0], [max_width, 0], [0, max_height], [max_width, max_height]])
M = cv2.getPerspectiveTransform(pts1, pts2)
image_roi = cv2.warpPerspective(img, M, (max_width, max_height))
#image_opencv = Image.fromarray(image_opencv)
return image_roi
#if __name__ == '__main__':
def get_roiFace(src, bboxes1, bboxes2):
#src = cv2.imread('./1.jpg')
img = src.copy()
#bboxes1 = np.array([[200, 720], [320, 660]], dtype=np.int32) #3.jpg
#bboxes1 = np.array([[800, 1130], [960, 1180]], dtype=np.int32) #2.jpg
#bboxes1 = np.array([[300, 240], [470, 240], [470,320], [300,320]], dtype=np.int32) #1.jpg
x11, y11, x12, y12 = bboxes1[0][0], bboxes1[0][1], bboxes1[1][0], bboxes1[1][1]
cv2.line(img, (x11, y11), (x12, y12), (0, 255, 0), thickness=2, lineType=4)
line1 = [x11, y11, x12, y12]
#bboxes2 = np.array([[480, 1010], [930, 800], [950, 850], [500, 1060]], dtype=np.int32) #3.jpg
#bboxes2 = np.array([[820, 1755], [1560, 2000], [1540, 2085], [800, 1840]], dtype=np.int32)#2.jpg
#bboxes2 = np.array([[510, 810], [1210, 810], [1210, 860], [510, 860]], dtype=np.int32)#1.jpg
x21, y21, x22, y22, x23, y23, x24, y24 = bboxes2[0][0], bboxes2[0][1], bboxes2[1][0], bboxes2[1][1], bboxes2[2][0], bboxes2[2][1], bboxes2[3][0], bboxes2[3][1]
h = point_to_point((x22, y22), (x23, y23))
w = point_to_point((x22, y22), (x21, y21))
cv2.line(img, (x21, y21), (x22, y22), (0, 255, 0), thickness=2, lineType=4)
cv2.line(img, (x22, y22), (x23, y23), (0, 255, 0), thickness=2, lineType=4)
cv2.line(img, (x23, y23), (x24, y24), (0, 255, 0), thickness=2, lineType=4)
cv2.line(img, (x24, y24), (x21, y21), (0, 255, 0), thickness=2, lineType=4)
x1_center, y1_center = (bboxes2[0][0] + bboxes2[1][0]) // 2, (bboxes2[0][1] + bboxes2[1][1]) // 2
x2_center, y2_center = (bboxes2[2][0] + bboxes2[3][0]) // 2, (bboxes2[2][1] + bboxes2[3][1]) // 2
line2 = [x1_center, y1_center, x2_center, y2_center]
#x1, y1 = line_point_line([[x11, y11], [x12, y12]], [[x1_center, y1_center], [x2_center, y2_center]])
x1, y1 = cross_point(line1, line2)
#calc k
#A, B, C = fit_line([x21, y21], [x22, y22])
#print('abc:', (A,B,C))
#k = (0-A)*1.0 / B
k, _ = calc_kb([x21, y21, x22, y22])
#print(k)
#degree = math.degrees(math.atan(k))
radians = math.atan(k) #k -> radians
if radians >= 0: #degree
#degree = 90 - abs(degree)
#radians = abs(radians)
#x1 = int(x1 - 0.5*h *math.cos(radians))
#y1 = int(y1 - 0.5*h *math.sin(radians))
x1 = x1
y1 = y1
#x4 = int(x1_center - 0.5*h *math.cos(radians)+h*math.sin(radians))
#y4 = int(y1_center - 0.5*h *math.sin(radians)-h*math.cos(radians))
x4 = int(x1_center + 0.8*h*math.sin(radians))
y4 = int(y1_center - 0.8*h*math.cos(radians))
#x3 = int(x1_center + (w//2 + h*1.5)*math.cos(radians)+h*math.sin(radians))
#y3 = int(y1_center + (w//2 + h*1.5)*math.sin(radians)-h*math.cos(radians))
x3 = int(x4 + (w//2 + h)*math.cos(radians))
y3 = int(y4 + (w//2 + h)*math.sin(radians))
x3_ = int(x1_center + (w//2 + h)*math.cos(radians))
y3_ = int(y1_center + (w//2 + h)*math.sin(radians))
line3 = [x3,y3,x3_,y3_]
x2,y2 = cross_point(line1,line3)
else:
radians = abs(radians)
#x1 = int(x1 - 0.5*h *math.cos(radians))
#y1 = int(y1 + 0.5*h *math.sin(radians))
x1 = x1
y1 = y1
#x4 = int(x1_center - 0.5*h *math.cos(radians)-h*math.sin(radians))
#y4 = int(y1_center + 0.5*h *math.sin(radians)-h*math.cos(radians))
x4 = int(x1_center - 0.8*h *math.sin(radians))
y4 = int(y1_center - 0.8*h *math.cos(radians))
#x3 = int(x1_center + (w//2 + h*1.5)*math.cos(radians)-h*math.sin(radians))
#y3 = int(y1_center - (w//2 + h*1.5)*math.sin(radians)-h*math.cos(radians))
x3 = int(x4 + (w//2 + h)*math.cos(radians))
y3 = int(y4 - (w//2 + h)*math.sin(radians))
x3_ = int(x1_center + (w//2 + h)*math.cos(radians))
y3_ = int(y1_center - (w//2 + h)*math.sin(radians))
line3 = [x3,y3,x3_,y3_]
x2,y2 = cross_point(line1,line3)
box = [[x1,y1],[x2,y2],[x3,y3],[x4,y4]]
box = adjust(np.array(box,dtype=np.int32))
roi = perspective_transformation(src, box)
#cv2.imwrite('face1.jpg', roi)
cv2.circle(img, (x1, y1), 1, (0, 0, 255), thickness=8)
cv2.circle(img, (x4, y4), 1, (0, 0, 255), thickness=8)
cv2.circle(img, (x3, y3), 1, (0, 0, 255), thickness=8)
cv2.circle(img, (x2, y2), 1, (0, 0, 255), thickness=8)
#cv2.circle(img, (x1_center, y1_center), 1, (255, 0, 0), thickness=4)
cv2.imwrite('img1.jpg', img)
return roi
def normalize_transform(gray_img):
'''
:param gray_img:
:return:
'''
Imin, Imax = cv2.minMaxLoc(gray_img)[:2]
Omin, Omax = 0, 255
a = float(Omax - Omin) / (Imax - Imin)
b = Omin - a * Imin
out = a * gray_img + b
out = out.astype(np.uint8)
return out
def linear_transform(img, a, b):
'''
:param img: [h, w, 3]
:param a: float
:param b: float
:return: out = a * img + b
'''
out = a * img + b
out[out > 255] = 255
out = np.around(out)
out = out.astype(np.uint8)
return out
if __name__ == '__main__':
src = cv2.imread('./1.jpg')
#bboxes1 = np.array([[200, 720], [320, 660]], dtype=np.int32) #3.jpg
#bboxes1 = np.array([[800, 1130], [960, 1180]], dtype=np.int32) #2.jpg
bboxes1 = np.array([[300, 240], [470, 240], [470,320], [300,320]], dtype=np.int32) #1.jpg
#bboxes2 = np.array([[480, 1010], [930, 800], [950, 850], [500, 1060]], dtype=np.int32) #3.jpg
#bboxes2 = np.array([[820, 1755], [1560, 2000], [1540, 2085], [800, 1840]], dtype=np.int32)#2.jpg
bboxes2 = np.array([[510, 810], [1210, 810], [1210, 860], [510, 860]], dtype=np.int32)#1.jpg
roi = get_roiFace(src, bboxes1, bboxes2)
cv2.imwrite('face1.jpg', roi)
'''
img = roi.copy()
b = img[:, :, 0]
g = img[:, :, 1]
r = img[:, :, 2]
b_out = normalize_transform(b)
g_out = normalize_transform(g)
r_out = normalize_transform(r)
inhance = np.stack((b_out, g_out, r_out), axis=-1)
cv2.imwrite('inhance2.jpg', inhance)
#raise
inhance = linear_transform(roi, 2.0, 10)
cv2.imwrite('inhance2_linear.jpg', inhance)
#cv2.imwrite('face2.jpg', roi)
###findcontours
roi_gray = cv2.cvtColor(inhance, cv2.COLOR_BGR2GRAY)#roi->inhance
#roi_gray = cv2.split(roi_gray)[2]
#cv2.imwrite('gray2.jpg', roi_gray)
#th, roi_binary = cv2.threshold(roi_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
#roi_binary = cv2.adaptiveThreshold(roi_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 5, 2)
roi_edge = cv2.Canny(roi_gray, 20, 200)
cv2.imwrite('roi_edge.jpg', roi_edge)
#find edge
roi_median = cv2.medianBlur(roi_gray, 3)
cv2.imwrite('median2.jpg', roi_median)
#roi_median = roi_gray
edge_x = cv2.Sobel(roi_median, cv2.CV_16S, 1, 0)
edge_y = cv2.Sobel(roi_median, cv2.CV_16S, 0, 1)
edge_x = cv2.convertScaleAbs(edge_x) # to uint8
edge_y = cv2.convertScaleAbs(edge_y)
#print('type(edgex):', type(edge_x))
cv2.imwrite('edge_x.jpg', edge_x)
cv2.imwrite('edge_y.jpg', edge_y)
#edge_blurx = cv2.GaussianBlur(edge_x, (5,5),0)
edge_blurx = edge_x
edge_binx = cv2.threshold(edge_blurx, 0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]#+cv2.THRESH_OTSU
#edge_binx = cv2.adaptiveThreshold(edge_blurx, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 5, 2)
#print('type(edge_binx):', type(edge_binx))
#edge_blury = cv2.GaussianBlur(edge_y, (5,5),0)
edge_blury = edge_y
edge_biny = cv2.threshold(edge_blury, 0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
#edge_biny = cv2.adaptiveThreshold(edge_blury, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 5, 2)
cv2.imwrite('edge_binx.jpg', edge_binx)
cv2.imwrite('edge_biny.jpg', edge_biny)
roi_edge = cv2.bitwise_or(edge_binx, edge_biny)
cv2.imwrite('roi_edge.jpg', roi_edge)
##
horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 5))
#roi_edge2 = cv2.dilate(roi_edge, horizontalStructure, iterations = 3)
roi_edge2 = cv2.morphologyEx(roi_edge, cv2.MORPH_CLOSE, horizontalStructure, iterations = 3)
cv2.imwrite('roi_edge2.jpg', roi_edge2)
'''