1.安装
2.基本使用 2-1.混合两张图片 1 2 3 4 5 6 7 8 9 10 11 12 import cv2img1 = cv2.imread("E:/OCR/PDF/a_pdf/0.png" ) img2 = cv2.imread("E:/OCR/PDF/a_pdf/1.png" ) alpha = 0.3 beta = 0.7 final_img = cv2.addWeighted(img1, alpha, img2, beta, 0.0 ) cv2.imshow("final_img" , final_img) cv2.waitKey(0 )
2-2.改变图像的对比度和亮度
对比度:最大像素强度和最小像素强度之差
亮度:指图像亮或暗的程度。通过给所有像素加上一个常数可以让图像变得更亮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import cv2import numpy as npimg = cv2.imread("img_path" ) new_img = np.zeros(img.shape, img.dtype) constract = 3.0 bright = 2 for y in range (img.shape[0 ]): for x in range (img.shape[1 ]): for c in range (img.shape[2 ]): new_img[y, x, c] = np.clip(constract * img[y, x, c] + bright, 0 , 255 ) cv2.imshow("img" , img) cv2.imshow("new_img" , new_img) cv2.waitKey(0 )
(特定像素值 * 对比度) + 亮度
2-3.往图像中添加文字
接受参数:
要添加文字的图像
要添加的文字
文字在图像上的位置
字体类型,支持以下的字体:
FONT_HERSHEY_SIMPLEX
FONT_HERSHEY_PLAIN
FONT_HERSHEY_DUPLEX
FONT_HERSHEY_COMPLEX
FONT_HERSHEY_TRIPLEX
FONT_HERSHEY_COMPLEX_SMALL
FONT_HERSHEY_SCRIPT_SIMPLEX
FONT_HERSHEY_SCRIPT_COMPLEX
字体大小
字体颜色
字体粗细
使用的线型
FILLED:完全填充线
LINE_4:四连通线
LINE_8:八连通线
LINE_AA:防锯齿线
1 2 3 4 5 6 7 8 9 import cv2import numpy as npimg = cv2.imread("img_path" ) cv2.putText(new_img, "This is a picture" , (230 , 50 ), cv2.FONT_HERSHEY_SIMPLEX, 0.8 , (0 , 255 , 0 ), 2 , cv2.LINE_AA) cv2.imshow("img" , img) cv2.waitKey(0 )
cv2.putText()不能在图像中添加中文,需要使用PIL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import cv2import numpy as npimg = cv2.imread("img_path" ) if isinstance (img1, np.ndarray): imgPIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) drawPIL = ImageDraw.Draw(imgPIL) font = ImageFont.truetype("font/simsun.ttc" , size=40 , encoding="utf-8" ) drawPIL.text((50 , 20 ), "这是一张图片" , (255 , 255 , 255 ), font=font) imgPutText = cv2.cvtColor(np.asanyarray(imgPIL), cv2.COLOR_RGB2BGR) cv2.imshow("imgPutText" , imgPutText) cv2.waitKey(0 )
2-4.平滑图像
均值滤波器(cv2.blur())
中值滤波器(cv2.medianBlur())
高斯滤波器(cv2.GaussianBlur())
双边滤波器(cv2.bilateralFilter())
1)均值滤波器 1 2 3 4 5 6 7 8 import cv2import numpy as npimg = cv2.imread("img_path" ) img_mean = cv2.blur(img1, (5 , 5 )) cv2.imshow("img_mean" , img_mean) cv2.waitKey(0 )
2)中值滤波器 是基本的图像平滑滤波器之一,是一种非线性滤波器,通过求临近像素的中位数来消除图像中的黑色噪音。
1 2 3 4 5 6 7 8 9 import cv2import numpy as npimg = cv2.imread("img_path" ) img_median = cv2.medianBlur(img1, 5 ) cv2.imshow("img_median" , img_median) cv2.waitKey(0 )
3)高斯滤波器 1 2 3 4 5 6 7 8 9 import cv2import numpy as npimg = cv2.imread("img_path" ) img_gaussian = cv2.GaussianBlur(img1, (5 , 5 ), 0 ) cv2.imshow("img_gaussian" , img_gaussian) cv2.waitKey(0 )
4)双边滤波器 1 2 3 4 5 6 7 8 9 import cv2import numpy as npimg = cv2.imread("img_path" ) img_bilateral = cv2.bilateralFilter(img1, 9 , 75 , 75 ) cv2.imshow("img_bilateral" , img_bilateral) cv2.waitKey(0 )
2-5.改变图像的形状
侵蚀:物理边界的像素减少
扩张:物体边界的像素增加
定义邻域核(neighborhood kernel),有如下三种定义方式:
MORPH_RECT:创建矩形核
MORPH_CROSS:创建十字形核
MORPH_ELLIPSE:创建椭圆形核
1)侵蚀操作作用核内的最小值产生一个新的像素 以下使用一个3x1的矩阵来发现每一行的最小值。
对于第一个元素来说,计算从前一个单元开始,因为左边的单元没有值,所以当它然是空白的,这种做法称为填充(padding)。所以第一个最小值在空白、141和157之间产生。结果141最小,所以右边矩阵的第一个元素是141.
然后,核向右平移,现在要考虑的单元是141、157和65,这次的最小值是65,所以新矩阵的第二个元素是65。
第三次的时候,核要比较157、65和空白,因为没有第三单元,所以最小值是65,也就是新矩阵的最后一个元素的值。
对于每个单元执行这种操作,就会得到右边的矩阵。
2)扩张操作作用核内的最大值产生一个新的像素 与侵蚀操作类似,只是取最大值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 - 侵蚀或扩张类型 - 核的大小 - 使用核的起始点 ```python import cv2 import numpy as np img = cv2.imread("img_path") 1 = 0 s2 = 10 s3 = 10 t1 = cv2.MORPH_RECT t2 = cv2.MORPH_CROSS t3 = cv2.MORPH_ELLIPSE temp1 = cv2.getStructuringElement(t1, (2 * s1 + 1, 2 * s1 + 1), (s1, s1)) temp2 = cv2.getStructuringElement(t2, (2 * s2 + 1, 2 * s2 + 1), (s2, s2)) temp3 = cv2.getStructuringElement(t3, (2 * s3 + 1, 2 * s3 + 1), (s3, s3)) final1 = cv2.erode(img1, temp1) final2 = cv2.erode(img1, temp2) final3 = cv2.erode(img1, temp3) cv2.imshow("final1", final1) cv2.imshow("final2", final2) cv2.imshow("final3", final3) cv2.waitKey(0)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import cv2import numpy as npimg = cv2.imread("img_path" ) d1 = 0 d2 = 10 d3 = 20 t1 = cv2.MORPH_RECT t2 = cv2.MORPH_CROSS t3 = cv2.MORPH_ELLIPSE temp1 = cv2.getStructuringElement(t1, (2 * d1 + 1 , 2 * d1 + 1 ), (d1, d1)) temp2 = cv2.getStructuringElement(t2, (2 * d2 + 1 , 2 * d2 + 1 ), (d2, d2)) temp3 = cv2.getStructuringElement(t3, (2 * d3 + 1 , 2 * d3 + 1 ), (d3, d3)) final1 = cv2.dilate(img1, temp1) final2 = cv2.dilate(img1, temp2) final3 = cv2.dilate(img1, temp3) cv2.imshow("final1" , final1) cv2.imshow("final2" , final2) cv2.imshow("final3" , final3) cv2.waitKey(0 )
2-6.实施图像阈值化 阈限化(thresholding)处理的主要原因是要做图像分割。
可以通过移除背景将物体从图像中提取出来。为此,需要先将图像转换成灰度格式,然后转换成二值格式——只有黑色与白色的图像。
提供一个参考像素值,然后将所有值大于或小于它的像素转换成黑色或白色。有如下五种阈限化:
二值:如果像素值大于参考像素值(阈值),就转换成白色(255),否则转换成黑色(0)
反向二值:如果像素值大于参考像素值(阈值),就转换成黑色(0),否则转换成白色(255)。刚好与普通二值型相反
截断:如果像素值大于惨开像素值(阈值),就转换成阈值,否则保持不变。
阈限到零:如果像素值大于参考像素值(阈值),则保持不变;否则转换成黑色(0)。
反向阈值到零:如果像素值大于参考像素值(阈值),就转换成黑色(0),否则保持不变。
使用cv2.threshold()函数做图像阈限化,参数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import cv2import numpy as npimg = cv2.imread("img_path" ) _, img0 = cv2.threshold(img, 50 , 255 , 0 ) _, img1 = cv2.threshold(img, 50 , 255 , 1 ) _, img2 = cv2.threshold(img, 50 , 255 , 2 ) _, img3 = cv2.threshold(img, 50 , 255 , 3 ) _, img4 = cv2.threshold(img, 50 , 255 , 4 ) cv2.imshow("img0" , img0) cv2.imshow("img1" , img1) cv2.imshow("img2" , img2) cv2.imshow("img3" , img3) cv2.imshow("img4" , img4) cv2.waitKey(0 )
2-7.计算梯度 使用索伯导数(Sobel derivative)做边缘检测。
边有两种方向:垂直方向和水平方向。针对这种算法,只有空间频率非常高的区域才算边。一个区域的空间频率是指这个区域内的细节丰富内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 - 输入图像 - 输入图像的深度 图像的深度越大,错过任一边界的概率就约低。可以根据需求试验下列所有参数,看看他们是否把边检测出来。 深度可以是以下类型: - -1(与原始图像的深度相同) - cv2.CV_16S - cv2.CV_32F - cv2.CV_64F - x的求导顺序 - y的求导顺序 - 核的大小 - 用于求导的缩放系数 - 作为标量加到公式中的差值 - 用于外推像素的边界类型 ```python import cv2 import numpy as np img = cv2.imread("img_path") cv2.GaussianBlur(img, (3, 3), 0) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) grad_x = cv2.Sobel(gray, cv2.CV_16S, 1, 0, ksize=3, scale=1, delta = 0, borderType=cv2.BORDER_DEFAULT) grad_y = cv2.Sobel(gray, cv2.CV_16S, 0, 1, ksize=3, scale=1, delta = 0, borderType=cv2.BORDER_DEFAULT) abs_grad_x = cv2.convertScaleAbs(grad_x) abs_grad_y = cv2.convertScaleAbs(grad_y) grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0) cv2.imshow("grad", grad) cv2.waitKey(0)
2-8.执行直方图均衡 直方图均衡用于调整图像的对比度。
我们首先画出像素强度分布的直方图,然后修改。
每张图像都关联一个累计概率函数。
直方图均衡使得这个函数具有线性趋势。
使用灰度图做直方图均衡
cv2.equalizeHist()
1 2 3 4 5 6 7 8 9 10 11 import cv2import numpy as npimg = cv2.imread("img_path" ) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img_eqlzd = cv2.equalizeHist(img) cv2.imshow("img" , img) cv2.imshow("img_eqlzd" , img_eqlzd) cv2.waitKey(0 )