虽然计算机视觉领域目前基本是以深度学习算法为主,但实际上不少时候对图片的不少处理方法,并不须要采用深度学习的网络模型,采用目前成熟的图像处理库便可实现,好比 OpenCV 和 PIL ,对图片进行简单的调整大小、裁剪、旋转,或者是对图片的模糊操做。html
因此本文主要是介绍用 OpenCV 实现一些基本的图像处理操做,本文的目录以下所示:python
原文地址:git
https://likegeeks.com/python-image-processing/github
代码和样例图片的地址:算法
https://github.com/ccc013/CodesNotes/tree/master/opencv_noteswindows
https://github.com/ccc013/CodesNotes/blob/master/opencv_notes/opencv_image_process_tutorial.ipynb数组
OpenCV 的安装仍是比较简单的,直接用 pip
命令在命令行安装便可,输入如下命令:网络
pip install opencv-python
验证是否安装成功,能够运行 python
命令,而后分别输入如下命令:函数
import cv2
运行成功,没有报错,即安装成功。学习
首先,仍是须要导入 cv2
模块:
import cv2
而后第一件事情就是读取图片,调用imread
函数便可,输入参数是图片的路径,以下代码所示:
# 读取图片 img = cv2.imread('example.jpg') print(f'type: {type(img)}') plt.axis('off') plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
而后打印读取的图片类型,能够知道是一个numpy
的多维数组,即矩阵的形式。
上述代码运行结果以下:
下面的全部功能实现,我都是在 jupyter notebook
上实现的,因此展现图片部分和原文有所不一样,原文展现图片代码是采用:
cv2.imshow('original image', img) cv2.waitKey(0)
而在 jupyter 中,须要先导入下面的库:
import matplotlib.pyplot as plt %matplotlib inline
而后直接调用 plt.imshow()
函数,不过 opencv 都须要作一个转换过程,即:
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
读取好图片后,接下来就是实现旋转图片,这里分为如下三个步骤:
cv2.getRotationMatrix2D()
获得旋转矩阵wrapAffine
实现旋转实现的代码以下所示:
# 获取图片的宽、高 height, width = img.shape[:2] print(height, width) rotationMatrix = cv2.getRotationMatrix2D((width/2, height/2), 45, .5) rotationImage = cv2.warpAffine(img, rotationMatrix, (width, height)) print(f'rotation image shape:{rotationImage.shape}') plt.imshow(cv2.cvtColor(rotationImage, cv2.COLOR_BGR2RGB))
结果以下所示:
裁剪图片的步骤以下:
实现代码以下所示:
img = cv2.imread('example.jpg') height, width = img.shape[:2] print(f'origin image shape:{img.shape}') # 设置裁剪后图片的大小 start_row = int(height * 0.15) start_col = int(width * 0.15) end_row = int(height * 0.85) end_col = int(width * 0.85) # 裁剪图片 cropped_image = img[start_row:end_row, start_col:end_col] print(f'crop image shape:{cropped_image.shape}') plt.axis('off') plt.imshow(cv2.cvtColor(cropped_image, cv2.COLOR_BGR2RGB))
效果以下图所示:
对图片进行调整大小的操做,采用的是resize()
函数,这里有两种方式进行调整大小:
fx, fy
参数;第一种方式的实现代码:
img = cv2.imread('example.jpg') height, width = img.shape[:2] print(f'origin image shape:{img.shape}') # 1 new_img = cv2.resize(img, (0, 0), fx=0.75, fy=0.75) print(f'new img shape:{new_img.shape}') plt.axis('off') plt.imshow(cv2.cvtColor(new_img, cv2.COLOR_BGR2RGB))
实现效果:
第二种方法的实现代码:
# 2 new_img = cv2.resize(img, (800, 800)) print(f'new img shape:{new_img.shape}') plt.axis('off') plt.imshow(cv2.cvtColor(new_img, cv2.COLOR_BGR2RGB))
实现结果以下所示:
在 Python 的 OpenCV 模块中并无特定的实现调整图片对比度的函数,但官方文档给出实现调整图片亮度和对比度的公式,以下所示:
new_img = a*original_img + b
官方文档地址:
https://docs.opencv.org/master/d3/dc1/tutorial_basic_linear_transform.html
这里公式中的 a
就是 $\alpha$, 表示图片的对比度,
b
是 $\beta$ ,数值范围是 -127 到 127;
要实现上述公式,能够采用 addWeighted()
方法,它输出的图片是一个 24 位的 0-255 范围的彩色图片。
其语法以下所示:
cv2.addWeighted(source_img1, alpha1, source_img2, alpha2, beta)
这个方法是接收两张输入的图片,而后根据 alpha1
和 alpha2
来将两种图片进行融合。
若是只是想调整图片的对比度,那么能够将第二个图片经过 Numpy 设置为 0。
因此,实现的代码以下所示:
import numpy as np img = cv2.imread('example.jpg') # 高对比度 hight_contrast_img = cv2.addWeighted(img, 2.5, np.zeros(img.shape, img.dtype), 0, 0) # 低对比度 low_contrast_img = cv2.addWeighted(img, 0.5, np.zeros(img.shape, img.dtype), 0, 0) plt.figure(figsize=(32, 16)) plt.subplot(3, 1, 1) plt.title('origin image') plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.subplot(3, 1, 2) plt.title('hight contrast image') plt.imshow(cv2.cvtColor(hight_contrast_img, cv2.COLOR_BGR2RGB)) plt.subplot(3, 1, 3) plt.title('low contrast image') plt.imshow(cv2.cvtColor(low_contrast_img, cv2.COLOR_BGR2RGB))
实现效果以下所示:
高斯模糊采用的是 GaussianBlur()
方法,采用高斯核,而且核的宽和高必须是正数,且是奇数。
高斯滤波主要用于消除高斯噪声,能够保留更多的图像细节,常常被称为最有用的滤波器。
实现的代码以下所示:
img = cv2.imread('example.jpg') blur_img = cv2.GaussianBlur(img, (7, 7), 3) plt.figure(figsize=(32, 32)) plt.subplot(1, 2, 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.subplot(1, 2, 2) plt.imshow(cv2.cvtColor(blur_img, cv2.COLOR_BGR2RGB))
实现效果:
对于中值模糊,就是用区域内的中值来代替本像素值,所以孤立的斑点,好比 0 或者 255 的数值很容易消除掉。
因此中值模糊主要用于消除椒盐噪声和斑点噪声。
实现代码:
img = cv2.imread('example.jpg') blur_img = cv2.medianBlur(img, 5) plt.figure(figsize=(32, 32)) plt.subplot(1, 2, 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.subplot(1, 2, 2) plt.imshow(cv2.cvtColor(blur_img, cv2.COLOR_BGR2RGB))
实现效果以下所示:
边缘检测主要是经过Canny()
方法,它实现了 Canny 边缘检测器,这也是目前最优的边缘检测器。
Canny()
方法的语法以下:
cv2.Canny(image, minVal, maxVal)
其中 minVal
和 maxVal
分别表示梯度强度值的最小值和最大值。
实现代码以下:
img = cv2.imread('example.jpg') edge_img = cv2.Canny(img, 100, 200) plt.figure(figsize=(32, 32)) plt.subplot(1, 2, 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.subplot(1, 2, 2) plt.imshow(cv2.cvtColor(edge_img, cv2.COLOR_BGR2RGB))
实现结果:
最简单的将图片转为灰度图的方法,就是读取的时候,代码以下所示:
img = cv2.imread("example.jpg", 0)
而另外一种方法就是用 BGR2GRAY
,实现代码:
img = cv2.imread('example.jpg') gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) plt.figure(figsize=(32, 32)) plt.subplot(1, 2, 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.subplot(1, 2, 2) plt.imshow(cv2.cvtColor(gray_img, cv2.COLOR_BGR2RGB))
实现效果:
检测一张图片的形心位置,实现步骤以下所示:
moments()
方法计算图片的 moments
;本例使用的图片以下:
实现代码:
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) moment = cv2.moments(gray_img) X = int(moment ["m10"] / moment["m00"]) Y = int(moment ["m01"] / moment["m00"]) cv2.circle(img, (X, Y), 50, (205, 114, 101), 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
实现的效果:
图像蒙版就是将一张图片做为另外一张图片的蒙版,或者是修改图片中的像素值。
本例中将采用HoughCircles()
方法来应用蒙版,这个方法能够检测图片中的圆,而后对这些圆应用蒙版。
本例采用的图片为:
实现代码:
img1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) circles = cv2.HoughCircles(gray_img, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=50, minRadius=0, maxRadius=0) circles = np.uint16(np.around(circles)) masking=np.full((img1.shape[0], img1.shape[1]),0,dtype=np.uint8) for j in circles[0, :]: cv2.circle(masking, (j[0], j[1]), j[2], (255, 255, 255), -1) final_img = cv2.bitwise_or(img1, img1, mask=masking) plt.imshow(cv2.cvtColor(final_img, cv2.COLOR_BGR2RGB))
实现效果:
实现提取图片的文字是经过安装使用谷歌的 Tesseract-OCR
,首先须要从下面这个网址中下载:
https://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-setup-3.05.02-20180621.exe
接着再进行安装:
pip install pytesseract
若是是 mac,安装步骤能够是这样的:
brew install tesseract pip install pytesseract
本例使用的图片:
实现代码以下所示:
import pytesseract pytesseract.pytesseract.tesseract_cmd = '/usr/local/bin/tesseract' img = cv2.imread('pytext.png') pytesseract.image_to_string(img)
实现结果:
注意这里须要设置 tesseract
的执行路径,两种方法,第一种是设置环境变量:
windows 版:https://blog.csdn.net/luanyongli/article/details/81385284
第二种是在代码中进行指定,即代码中pytesseract.pytesseract.tesseract_cmd = '/usr/local/bin/tesseract'
,
这里我用的是 Mac,因此这个路径能够在命令行中输入which tesseract
来找到。
在本例中,使用的图片以下:
首先仍是先读取图片,并转换为灰度图:
接着采用 bitwise_not
方法将背景和文字颜色进行交换,变成白字黑底:
接着分别找到 x,y 坐标中大于 0 值的像素值,并经过minAreaRect()
计算获得歪曲的角度,接着就是计算要修正的角度,而后再经过以前旋转图片的方法来修正,实现代码和结果以下:
完整的实现代码:
import cv2 import numpy as np img = cv2.imread('Skewed-text-image.png') gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray_img = cv2.bitwise_not(gray_img) coordinates = np.column_stack(np.where(gray_img > 0)) ang=cv2.minAreaRect(coordinates)[-1] if ang<-45: angle=-(90+ang) else: angle=-ang height, width = img.shape[:2] center_img = (width / 2, height / 2) rotationMatrix = cv2.getRotationMatrix2D(center_img, angle, 1.0) rotated_img = cv2.warpAffine(img, rotationMatrix, (width, height), borderMode = cv2.BORDER_REFLECT) plt.imshow(cv2.cvtColor(rotated_img, cv2.COLOR_BGR2RGB))
在本次例子中实现检测图片中的绿色区域,使用的图片:
首先是读取图片后,转换到 HSV 空间:
接着须要经过 Numpy 设置绿色像素值的上下范围区间:
lower_green = np.array([34, 177, 76]) upper_green = np.array([255, 255, 255])
接着经过 inRange()
方法来判断输入图片中是否包含在设置后的绿色区间范围内,若是有,那就表示检测到绿色这种颜色的像素区域。
完整实现的代码:
import cv2 import numpy as np img = cv2.imread("pycolor.png") hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) plt.imshow(cv2.cvtColor(hsv_img, cv2.COLOR_BGR2RGB)) lower_green = np.array([34, 177, 76]) upper_green = np.array([255, 255, 255]) masking = cv2.inRange(hsv_img, lower_green, upper_green) plt.imshow(cv2.cvtColor(masking, cv2.COLOR_BGR2RGB))
实现结果:
OpenCV 中提供了下面 4 种图像去噪的方法:
fastNlMeansDenoising()
:从灰度图中降噪;fastNlMeansDenoisingColored()
:从彩色图片中降噪fastNlMeansDenoisingMulti()
:从灰度图片帧(灰度视频)中降噪;fastNlMeansDenoisingColoredMulti()
:从彩色图片帧中降噪本次例子会用第二种方法:fastNlMeansDenoisingColored()
实现的代码以下所示:
import cv2 img = cv2.imread('example.jpg') result = cv2.fastNlMeansDenoisingColored(img,None,20,10,7,21) plt.figure(figsize=(32, 32)) plt.subplot(1, 2, 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.subplot(1, 2, 2) plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
其中对于方法fastNlMeansDenoisingColored()
的个参数分别是:
result
变量里;实现结果:
轮廓是图片中将连续的点链接在一块儿的曲线,一般检测轮廓的目的是为了检测物体。本例中使用的图片以下:
检测轮廓的步骤以下:
threshold
() 找到阈值,一般设置 127-255 的区间findContours()
进行检测轮廓,具体使用方法能够查看官方文档:https://docs.opencv.org/3.4.2/d3/dc0/group__imgproc__shape.html#ga17ed9f5d79ae97bd4c7cf18403e1689adrawContours()
来绘制画好的轮廓,而后展现出来实现代码:
import cv2 img = cv2.imread('opencv_contour_example.png') gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) retval, thresh = cv2.threshold(gray_img, 127, 255, 0) img_contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(img, img_contours, -1, (0, 255, 0)) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
实现效果:
移除图片背景的实现思路是这样的:
np.zeros
生成一个蒙版 mask;bitwise_and
运算符来结合检测轮廓后的图片和蒙版 mask本次样例使用的原图:
实现代码:
import cv2 import numpy as np img = cv2.imread("opencv_bg.png") gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) img_contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2] img_contours = sorted(img_contours, key=cv2.contourArea) for i in img_contours: if cv2.contourArea(i) > 100: break mask = np.zeros(img.shape[:2], np.uint8) cv2.drawContours(mask, img_contours, -1, 255, -1) new_img = cv2.bitwise_and(img, img, mask=mask) plt.figure(figsize=(32, 32)) plt.subplot(1, 2, 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.subplot(1, 2, 2) plt.imshow(cv2.cvtColor(new_img, cv2.COLOR_BGR2RGB))
实现结果:
本文是简单介绍了基于 opencv 实现的一些图像处理操做,从基础的旋转,裁剪,调整大小,到模糊图片,边缘检测,修正歪曲文字,去噪,检测轮廓等操做,都给出了基础的实现代码,若是须要更深刻了解,这里推荐:
最后,原文地址:
https://likegeeks.com/python-image-processing/
代码和样例图片的地址:
https://github.com/ccc013/CodesNotes/tree/master/opencv_notes
https://github.com/ccc013/CodesNotes/blob/master/opencv_notes/opencv_image_process_tutorial.ipynb
欢迎关注个人公众号--算法猿的成长