引言
在做图像处理方面的毕设,希望在正式处理图像之前先把图像处理得比较“正”,比如对下面的图片,希望它是堂正的,就不用歪着头看。所以用python的cv库写了一个自动矫正的程序。
注意
:为了让图像和背景尽量区别,最好使用纯黑的背景(比如黑衣服,还能吸光)
步骤
1.提取目标的边界,比如课本
2.将边界之内的部分填充白色,那么这张图片就变成了掩码
3.根据掩码,将原来的图片扣到新的图片里
4.根据边界的轮廓得到它的最小外接矩形
5.根据矩形的偏斜角度,旋转图像
代码
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import cv2
def correctImage(path):
img = cv2.imread('test2.bmp')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
"""将图片转化成二值图像"""
ret, binary = cv2.threshold(gray,100,255,cv2.THRESH_BINARY)
"""
*** cv2.finContours 函数能求取图像的边界,
返回的第一个值是用list存储的边界的数组每个边界又有多个点来组成
*** cv2.RETR_EXTERNAL 参数的含义是仅求取外围的边界
"""
contours, hierarchy = cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
"""
*** 下面的循环遍历了边界,找到含有最多点的那个边界的下标
*** 这是我观察发现的(没有科学的论证),有其中一个边界的点是最多的,基本能通过这个边界画出物体的轮廓
"""
m = 0;index = 0
for i in range(len(contours)):
if len(contours[i]) > m:
m = len(contours[i])
index = i
"""
*** cv2.minAreaRect 函数能根据点集求最小的外接矩形
(rect, rect[0] = 矩形中心, rect[1] = 矩形长和宽, rect[3] = 矩形的角度)
角度的大小是[0,90], 表示的是x轴逆时针旋转到与rect的一边重合的角度,重合的那条边是举行的宽。
"""
rect = cv2.minAreaRect(contours[index])
"""
*** cv2.drawContours( #函数能将边界画到图像里
binary, #第一个参数是目标图像
contours=contours, #边界集
contourIdx=-1, #选择的边界的序号,-1表示选择集合内的所有的边界
thickness=-1, #表示边界内的图形的填充方式,-1表示filled方式,也就是填满颜色
color=(255) ) #表示填充的颜色,255表示填充白色
"""
dst = np.zeros((img.shape))
cv2.drawContours(binary,contours=contours,contourIdx=-1,color=(255),thickness=-1)
"""
cv2.copyTo(src,mask) 根据mask(掩码)来将img填充到dst
"""
dst = cv2.copyTo(img,binary)
"""
*** cv2.getRotationMatrix2D( #根据输入的参数,返回旋转矩阵(因为对图像的旋转操作是采用的矩阵相乘)
centry, #旋转中心
angel, #旋转角度
scale #缩放
)
*** cv2.warpAffine(对图像进行旋转和缩放
1st, #输入图像
2sc, #旋转矩阵
3rd, #输出图像大小
4th, #输出
5th, #flag
6th #填充颜色
)
"""
angel = abs(rect[2])
if angel > 60:
angel = 90 - angel
mat = cv2.getRotationMatrix2D(rect[0],angel, 1)
rotimg = np.zeros((img.shape))
rotimg = cv2.warpAffine(dst,mat,(img.shape[1],img.shape[0]),rotimg,1,0)
im1 = img
im2 = binary
im3 = dst
im4 = rotimg
plt.subplot(2,2,1),plt.title('source')
plt.imshow(im1,)
plt.subplot(2,2,2),plt.title('contours')
plt.imshow(im2,'gray')
plt.subplot(2,2,3),plt.title('cppyTo')
plt.imshow(im3)
plt.subplot(2,2,4),plt.title('final')
plt.imshow(im4)
plt.show()
correctImage('')
结果
第一张是原图,第二张是提取到的源码
第三张是根据掩码得到的填充
第四章是最终的旋转后的图形
左下角有一点缺陷,如果多几个灯光应该可以改正,总体效果还可以
参考
https://www.cnblogs.com/skyfsm/p/6902524.html