71 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			71 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								# 图像的透视校正
							 | 
						||
| 
								 | 
							
								import cv2
							 | 
						||
| 
								 | 
							
								import numpy as np
							 | 
						||
| 
								 | 
							
								import math
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 读入待处理的图像并显示
							 | 
						||
| 
								 | 
							
								img = cv2.imread("./data/shu3.jpg")
							 | 
						||
| 
								 | 
							
								cv2.imshow("1_yuanshituxima", img)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 灰度化 并显示
							 | 
						||
| 
								 | 
							
								img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
							 | 
						||
| 
								 | 
							
								cv2.imshow("2.huidu", img_gray)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 模糊化处理 去掉过小的细节
							 | 
						||
| 
								 | 
							
								blurred = cv2.GaussianBlur(img_gray, (5, 5), 0)
							 | 
						||
| 
								 | 
							
								cv2.imshow("3.mohu", blurred)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 膨胀-抖小的细节合并
							 | 
						||
| 
								 | 
							
								dilate = cv2.dilate(blurred, (3, 3))
							 | 
						||
| 
								 | 
							
								cv2.imshow("4_pengzhang", dilate)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 边缘提取
							 | 
						||
| 
								 | 
							
								canny = cv2.Canny(dilate, 50, 240)
							 | 
						||
| 
								 | 
							
								cv2.imshow("5_bianyuntiqu", canny)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 轮廓检测
							 | 
						||
| 
								 | 
							
								imag, cnts, hie = cv2.findContours(canny.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 绘制轮廓
							 | 
						||
| 
								 | 
							
								img_cnt = cv2.drawContours(img.copy(), cnts, -1, (0, 0, 255), 2)
							 | 
						||
| 
								 | 
							
								cv2.imshow("6_lunkuxian", img_cnt)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								docCnt = None  # 定义一个空数组
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 计算面积, 排序
							 | 
						||
| 
								 | 
							
								if len(cnts) > 0:
							 | 
						||
| 
								 | 
							
								    cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
							 | 
						||
| 
								 | 
							
								    for c in cnts:
							 | 
						||
| 
								 | 
							
								        peri = cv2.arcLength(c, True)  # 求出该轮廓线的周长
							 | 
						||
| 
								 | 
							
								        approx = cv2.approxPolyDP(c, 0.02 * peri, True)  # 轮廓线的多边形组合
							 | 
						||
| 
								 | 
							
								        if len(approx) == 4:  # 找到边为4的多边形
							 | 
						||
| 
								 | 
							
								            docCnt = approx  # 将找到的多边形赋值给另外一个变量docCnt
							 | 
						||
| 
								 | 
							
								            break
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 绘制找到的四边形的点,画圆
							 | 
						||
| 
								 | 
							
								points = []
							 | 
						||
| 
								 | 
							
								for peak in docCnt:
							 | 
						||
| 
								 | 
							
								    peak = peak[0]
							 | 
						||
| 
								 | 
							
								    print("peak:", peak)
							 | 
						||
| 
								 | 
							
								    cv2.circle(img_cnt, tuple(peak), 10, (0, 255, 0), 2)  # 圆所在的图像, 圆心, 半径, 颜色, 线宽
							 | 
						||
| 
								 | 
							
								    points.append(peak)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								cv2.imshow("7-sibianxingdingdian", img_cnt)
							 | 
						||
| 
								 | 
							
								print("points:", points)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 校正
							 | 
						||
| 
								 | 
							
								# 原纸张逆时针方向的4个角点
							 | 
						||
| 
								 | 
							
								src = np.float32([points[0], points[1], points[2], points[3]])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# 根据勾股定理计算宽度,再做透视变换
							 | 
						||
| 
								 | 
							
								h = int(math.sqrt((points[1][0] - points[0][0]) ** 2 + (points[1][1] - points[0][1]) ** 2))  # 高度
							 | 
						||
| 
								 | 
							
								w = int(math.sqrt((points[2][0] - points[1][0]) ** 2 + (points[2][1] - points[1][1]) ** 2))  # 宽度
							 | 
						||
| 
								 | 
							
								print("w, h", w, h)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								dst = np.float32([[0, 0], [0, h], [w, h], [w, 0]])
							 | 
						||
| 
								 | 
							
								M = cv2.getPerspectiveTransform(src, dst)  # 生成透视矩阵
							 | 
						||
| 
								 | 
							
								result = cv2.warpPerspective(img.copy(), M, (w, h))  # 透视变换
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								cv2.imshow("8_leguo", result)
							 | 
						||
| 
								 | 
							
								cv2.waitKey()
							 | 
						||
| 
								 | 
							
								cv2.destroyAllWindows()
							 |