功能:
1.查看图片分辨率
2.查看图片exif信息 来确定文件是否经修改
3.对比图片和模板图片 标记处不同之处
> import sys import cv2
> import numpy as np from PIL
> import Image
Open Source Computer Vision Library.OpenCV于1999年由Intel建立,如今由Willow Garage提供支持。OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、MacOS操作系统上。它轻量级而且高效——由一系列 C 函数和少量C++类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
PIL可以做很多和图像处理相关的事情:
图像归档(Image Archives)。PIL非常适合于图像归档以及图像的批处理任务。你可以使用PIL创建缩略图,转换图像格式,打印图像等等。
图像展示(Image Display)。PIL较新的版本支持包括Tk PhotoImage,BitmapImage还有Windows DIB等接口。PIL支持众多的GUI框架接口,可以用于图像展示。
图像处理(Image Processing)。PIL包括了基础的图像处理函数,包括对点的处理,使用众多的卷积核(convolution kernels)做过滤(filter),还有颜色空间的转换。PIL库同样支持图像的大小转换,图像旋转,以及任意的仿射变换。PIL还有一些直方图的方法,允许你展示图像的一些统计特性。这个可以用来实现图像的自动对比度增强,还有全局的统计分析等。
> def preprocess(gray):
> # 1. Sobel算子,x方向求梯度
> sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 0, ksize = 3)
> # 2. 二值化
> ret, binary = cv2.threshold(sobel, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY)
>
> # 3. 膨胀和腐蚀操作的核函数
> element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 9))
> element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (24, 6))
>
> # 4. 膨胀一次,让轮廓突出
> dilation = cv2.dilate(binary, element2, iterations = 1)
>
> # 5. 腐蚀一次,去掉细节,如表格线等。注意这里去掉的是竖直的线
> erosion = cv2.erode(dilation, element1, iterations = 1)
>
> # 6. 再次膨胀,让轮廓明显一些
> dilation2 = cv2.dilate(erosion, element2, iterations = 3)
>
> # 7. 存储中间图片
> #cv2.imwrite("binary.png", binary)
> #cv2.imwrite("dilation.png", dilation)
> #cv2.imwrite("erosion.png", erosion)
> #cv2.imwrite("dilation2.png", dilation2)
>
> return dilation2
索贝尔算子(Sobeloperator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量。
Sobel算子依然是一种过滤器,只是其是带有方向的。
dst = cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])
前四个是必须的参数:
- src参数是需要处理的图像;
- ddepth参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
- dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
其后是可选的参数:
- ksize是Sobel算子的大小,必须为1、3、5、7。
- scale是缩放导数的比例常数,默认情况下没有伸缩系数;
- delta是一个可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中;
- borderType是判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT。
图像二值化( Image Binarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。
threshold:固定阈值二值化
ret, dst = cv2.threshold(src, thresh, maxval, type)
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
thresh: 阈值
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
形态学操作其实就是改变物体的形状,比如腐蚀就是"变瘦",膨胀就是"变胖"。形态学操作一般作用于二值化图,来连接相邻的元素或分离成独立的元素。腐蚀和膨胀是针对图片中的白色部分。
形态学处理的核心就是定义结构元素,在OpenCV-Python中,可以使用其自带的getStructuringElement函数
二维结构元素可以理解成一个二维矩阵,矩阵元素的值为0或者1;通常结构元素要小于待处理的图像。
getStructuringElement函数会返回指定形状和尺寸的结构元素。
> def findTextRegion(img):
> region = []
>
> # 1. 查找轮廓
> contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
>
> # 2. 筛选那些面积小的
> for i in range(len(contours)):
> cnt = contours[i]
> # 计算该轮廓的面积
> area = cv2.contourArea(cnt)
>
> # 面积小的都筛选掉
> if(area < 1000):
> continue
>
> # 轮廓近似,作用很小
> epsilon = 0.001 * cv2.arcLength(cnt, True)
> approx = cv2.approxPolyDP(cnt, epsilon, True)
>
> # 找到最小的矩形,该矩形可能有方向
> rect = cv2.minAreaRect(cnt)
> #print ("rect is: ")
> #print (rect)
>
> # box是四个点的坐标
> box = cv2.boxPoints(rect)
> box = np.int0(box)
>
> # 计算高和宽
> height = abs(box[0][1] - box[2][1])
> width = abs(box[0][0] - box[2][0])
>
> # 筛选那些太细的矩形,留下扁的
> if(height > width * 1.2):
> continue
>
> region.append(box)
>
> return region
> def detect(img,module):
> # 1. 转化成灰度图
> gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
> gray1 = cv2.cvtColor(module, cv2.COLOR_BGR2GRAY)
> # 2. 形态学变换的预处理,得到可以查找矩形的图片
> dilation = preprocess(gray)
> dilation1 = preprocess(gray1)
> # 3. 查找和筛选文字区域
> region = findTextRegion(dilation)
> region1 = findTextRegion(dilation1)
> #删除重复部分
> more=delete(region1,region)
> less=delete(region,region1)
> # 4. 用绿线画出这些找到的轮廓
> for box in more:
> cv2.drawContours(img, [box], 0, (0,0,200), 2)
> for box in less:
> cv2.drawContours(img, [box], 0, (0,200,0), 2)
> cv2.namedWindow("img", cv2.WINDOW_NORMAL)
> cv2.imshow("img", img)
> print("有",len(less)+len(more),"处文字位置与模板不符")
> # 带轮廓的图片
> #cv2.imwrite("contours.png", img)
> cv2.waitKey(0)
> cv2.destroyAllWindows() def compare(list1,list2):
> d=0
> for i in range(len(list1)):
> if abs(list1[i][1]-list2[i][1])+abs(list1[i][0]-list2[i][0])>117:
> d=d+1
> return d
> def delete(region1,region):
> l=list(region)
> l1=list(region1)
> for i in l1:
> for j in range(len(l)):
> if compare(i,l[j-1])==0:
> del(l[j-1])
> return l if __name__ == '__main__':
> # 读取文件
> modulePath='2.jpg'
> imagePath = '1.jpg'
> module = cv2.imread(modulePath)
> img = cv2.imread(imagePath)
> #1.查看文件分辨率
> im=Image.open(imagePath)
> print('分辨率:',im.info['dpi'])
> #2.查看文件exif信息
> if hasattr(im,'_getexif')or hasattr(img,'adobe'):
> print('文件经过修改,信息如下:',im.info)
> else:
> print("文件没有修改痕迹")
> #3.判断文字位置是否与模板相符
> detect(img,module)
参考资料:
https://www.jianshu.com/p/eacaa97cb2f7
https://blog.csdn.net/sinat_21258931/article/details/61418681