#图像透视变换--矫正 #根据最大的5边形进行透视变换 #获取最大和最次长 周长对应的轮廓 #该轮廓进行5边形拟合逼近 #进行透视变换:应用两线交点 import numpy as np import cv2 #大津阈值法 OSTU def myApprox(con,pointnum=5):# con为预先得到的最大轮廓 num = 0.001 # 初始化时不需要太小,因为四边形所需的值并不很小 ep = num * cv2.arcLength(con, True) con = cv2.approxPolyDP(con, ep, True) while (1): if len(con) == pointnum:#防止程序崩溃设置的==pointnum break else: num = num * 1.5 if num >2: break ep = num * cv2.arcLength(con, True) con = cv2.approxPolyDP(con, ep, True) continue return con #多边形矫正 def Polygon_correction(img): if len(img.shape) > 2: img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) contours, hierarchy = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) perimeter_list, area_list, cnt_list, center_lsit, box_list = [], [], [], [], [] ori_img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) ori_w,ori_h = ori_img.shape[0],ori_img.shape[1] print('ori_w,ori_h:',ori_w,ori_h) #ori_img = cv2.drawContours(ori_img, contours, -1, (0, 0, 255), 2) cv2.imshow('binary7', img) cv2.waitKey(0) cv2.destroyAllWindows() #筛选面积最大的三个候选轮廓 if len(contours) > 0: cnts = sorted(contours, key=cv2.contourArea, # 根据该函数计算的结果排序 reverse=True) cnts = cnts[:2] docCnt =None x, y, w, h = 0,0,ori_w,ori_h for cnt in cnts: #逼近法五边形拟合 approx =myApprox(cnt, pointnum=5) if len(approx)==5: docCnt = approx x, y, w, h = cv2.boundingRect(docCnt) #左上角,w,h # 绘制矩形 #cv2.rectangle(ori_img, (x, y + h), (x + w, y), (0, 255, 255)) break #获取得到五边形边框五个原始点 if not docCnt is None: points = [] #逆时针旋转排序,五个点 for doc in docCnt: peak = doc[0] # 在角点绘制小圆圈 #cv2.circle(ori_img, tuple(peak), 10, (0, 0, 255), 2) #橙色 points.append(tuple(peak)) p1, p2, p3, p4, p5 = points[0], points[1], points[2], points[3], points[4] #求四点确定的两条线段的交点,p1,p2,crossp,p5 作为ori转移矩阵前坐标点 from util import get_crosss_point crossp = get_crosss_point(p2, p3, p4, p5) #如果有交点,让交点作为四个点之一,如果无交点则选择点3或则点4即可 if crossp is not None: src = np.float32([p1,p2,crossp,p5]) #外接矩阵,水平垂直矩形 afterp1 = (x, y) afterp2 = (x, y + h-1) afterpcrossp = (x + w-1, y + h-1) afterp5 = (x + w-1, y) afterpoints = np.float32([afterp1, afterp2, afterpcrossp, afterp5]) else: src = np.float32([p1,p2,p3,p5])#存在一定误差 #根据自己需求得到多边形点 xmin, ymin = np.array(points)[:, 0].min(), np.array(points)[:, 1].min() xmax, ymax = np.array(points)[:, 0].max(), np.array(points)[:, 1].max() sigma = (xmax - p3[0] + ymax - p4[1])/2 sigma = int(sigma) afterp1 = (xmin, ymin) afterp2 = (xmin, ymax) afterp3 = (xmax - sigma, ymax) afterp4 = (xmax, ymax - sigma) afterp5 = (xmax, ymin) afterpoints = [afterp1, afterp2, afterp3,afterp5] print("原始点:", src) print("after点:",afterpoints) m = cv2.getPerspectiveTransform(src,afterpoints) result = cv2.warpPerspective(ori_img, m,(ori_h,ori_w)) # 透视变换 cv2.circle(result, afterp1, 5, (0, 255, 0), 2) cv2.circle(result, afterp2, 5, (0, 255, 0), 2) cv2.circle(result, afterpcrossp, 5, (0, 255, 0), 2) cv2.circle(result, afterp5, 5, (0, 255, 0), 2) print(result.shape) cv2.polylines(result,[np.array(afterpoints, np.int32)], True,(255, 255, 0),1) cv2.imshow('result', result) cv2.waitKey(0) cv2.destroyAllWindows() return result else: return img else: return img if __name__ == '__main__': img = cv2.imread('./data/binary7.png')#二值图 afterPolygonimg = Polygon_correction(img)
ps:求交点函数,链接为:(85条消息) python 已知四点,两条线,求交点_Lee魅儿的博客-CSDN博客