【算法与数据结构】图像中涉及图像处理以及直线方程等坐标变换(备忘录)

#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)
    '''

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值