| 理论
基础理论没仔细看,这部分先留空,有时间再补,主要是根据网上代码修改先应用起来
| 代码
对外网的代码修改了一下,主要针对形状为矩形的主体,应用平面变换将原图形铺满整个页面,代码如下:
# opencv 4.5.3
# python 3.7
# 将图片获取的四个角点重新排序成:左上角点 右上角点 左下角点和右下角点
def reorder(myPoints):
myPoints = myPoints.reshape((4,2))
myPointsNew = np.zeros((4,1,2),np.int32)
add = myPoints.sum(1)
myPointsNew[0] = myPoints[np.argmin(add)]
myPointsNew[3] = myPoints[np.argmax(add)]
diff = np.diff(myPoints, axis=1)
myPointsNew[1] = myPoints[np.argmin(diff)]
myPointsNew[2] = myPoints[np.argmax(diff)]
return myPointsNew
# 矩形旋转
def getWarp(img,approx):
#print(approx.shape)
approx = reorder(approx)
pts1 = np.float32(approx)
pts2 = np.float32([[0,0],[width,0],[0,height],[width,height]])
# 核心函数
matrix = cv.getPerspectiveTransform(pts1, pts2)
imgOutput = cv.warpPerspective(img, matrix, (width,height))
return imgOutput
# 获取待调整的矩形位置
def getContours(img):
contours, hierarchy = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
for cnt in contours: # cnt 是一系列点的集合
area = cv.contourArea(cnt)
if area > 5000:
#cv.drawContours(imgContour, cnt, -1, (255, 0, 0), 3)
peri = cv.arcLength(cnt, True)
approx = cv.approxPolyDP(cnt, 0.02 * peri, True)
# 检测到矩形
if len(approx == 4):
# cv.drawContours(imgContour, approx, -1, (255, 0, 0), 20)
return approx
return []
if __name__ == "__main__":
# 图像旋转
height, width = imgRGB.shape[:2]
imgBlue = imgRGB[:,:,0]
approx = getContours(imgBlue)
imgDeskew = getWarp(imgRGB, approx)
▶ 根据网上的说法,平面变换(即坐标变换)包括:仿射变换和透视变换,上面应用的就是透视变换,两者区别在于:仿射变换对图像保持平行四边形的平行性质,透视变换功能上更强大保持为四边形。因此前者是后者的一部分。
▶ opencv也有仿射变换函数,getRotationMatrix2D和warpAffine,某些情况下图片的位置会出错,如下所示,绕中心旋转后的主体并不是完全匹配原画布大小,而且会产生蓝色三角形的“重影”,具体处理方法有待摸索。也有可能某些参数设置错误才导致下面的结果