学习教程书本:OpenCV计算机视觉开发实战(基于python)
均来自与书本总结,图片为书上代码运行图。
imgproc的模块名称是由image(图像)和process(处理)两个单词的缩写组合而成的,是重要的图像处理模块,主要包括图像滤波、几何变换、直方图、特征检测与目标检测等。
一、颜色变换cvtColor
颜色变换时imgproc模块中一个常用的功能。在进行图像处理时需要用到灰度图、二值图、HSV、HSi等颜色制式,OpenCV提供了cvtColor()函数来实现这些功能。
cvtColor函数声明:
cvtColor(src, code[, dst[, dstCn]]) -> dst
- src:表示输入的图像,即要进行颜色空间变换的原图像,可以是数组矩阵;
- code:表示颜色空间转换代码,即在此确定将什么制式的图片转换成什么制式的图片;
- dst:表示输出与src相同大小和深度的图像,即进行颜色空间变换后存储图像;
- dstCn:表示目标图像通道数,默认取值为0,如果参数为0,则从src和代码自动获得通道的数量。
在OpenCV中,其默认的颜色制式排列时BGR而非RGB。对于24位颜色图像来说,前8位时蓝色,中间8位时绿色,最后8位是红色。
我们常用的颜色空间转换有两种:将BGR转换为Gray或HSV。
例如:将图片转换为灰度图和HSV
import cv2
#将图片转换成灰度图
src_image = cv2.imread("test.jpg")
gray_image = cv2.cvtColor(src_image, cv2.COLOR_BGR2GRAY)
#将图片转换成HSV
hsv_image = cv2.cvtColor(src_image, cv2.COLOR_BGR2HSV)
cv2.imshow("src_image", src_image)
cv2.imshow("gray_image", gray_image)
cv2.imshow("hsv_image", hsv_image)
cv2.waitKey(0)
运行结果:
二、画基本图形
1、画点
在OpenCV中,点分为2D平面中的点和3D平面中的点,区别就是3D中点多了一个z坐标。
比如定义一个点:
pt = (100, 200) #横坐标x = 100,纵坐标y = 200
2、画矩形
全局函数rectangle用来通过对角线上的两个顶点绘制矩形。函数声明如下:
cv.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]] ) -> img
cv.rectangle(img, rec, color[, thickness[, lineType[, shift]]] ) -> img
- img:表示矩形所在的图像;
- pt1:表示矩形的一个顶点:
- pt2:表示矩形对角线上的另一个顶点;
- color:表示线条颜色(BGR)或亮度(灰度图像,grayscale image);
- thickness:表示组成矩形的线条的粗细程度;
- line_type:表示线条的类型;
- shift:表示坐标点的小数点位数。
例如:
import cv2 as cv
img = cv.imread("test.jpg")
# (10,10)和(30,40)都是坐标,(255,0,0)是BGR形式的颜色,显示蓝色,线条粗细值2
img1=cv.rectangle(img,(10,10),(30,40),(255,0,0),2)
cv.imwrite("res.jpg",img1)
cv.imshow("res", img1)
cv.waitKey(0)
运行结果:
3、画圆
全局函数circle用来绘制或填充一个给定圆心和半径的圆。函数声明如下:
cv.circle(img, center, radius, color[, thickness[, lineType[, shift]]]) -> img
- img:表示输入的图像;
- center:表示圆心坐标;
- radius:表示圆的半径;
- color:表示圆的颜色,是BGR形式;
- thickness:线条的粗细程度,thickness = -1表示被填充;
- lineType:线条的类型;
- shift:圆心坐标点和半径值的小数点位数。
代码实例:
import numpy as np
import cv2 as cv
img = cv.imread("test.jpg")
point_size = 10
point_color = (0, 0, 255) # BGR
thickness = -1
# 要画的点的坐标
points_list = [(16, 16), (35, 40) ]
for point in points_list:
cv.circle(img, point, point_size, point_color, thickness)
thickness = 4
# 画圆,圆心为:(60, 60),半径为:60,颜色为:point_color,实心线
cv.circle(img, (60, 60), 60, point_color, 0)
cv.namedWindow("image")
cv.imshow('image', img)
cv.waitKey (10000) # 显示 10000 ms 即 10s 后消失
cv.destroyAllWindows()
运行效果:
4、画椭圆
函数ellipse用来绘制或者填充一个简单的椭圆弧或椭圆扇形。函数声明如下:
Ellipse(img, center, axes, angle, start_angle, end_angle, color, thickness=1, lineType=8, shift=0) → None
- img:表示输入的图像;
- center:表示圆心坐标;
- axes :表示轴的长度;
- angle:表示偏转的角度;
- start_angle:表示圆弧起始角的角度;
- end_angle:表示圆弧终结角的角度;
- color:表示圆的颜色,是BGR形式;
- thickness:线条的粗细程度,thickness = -1表示被填充;
- lineType:线条的类型;
- shift:圆心坐标点和数轴的精度。
5、画线段
在OpenCV中,函数line用来实现画线段,函数声明如下:
line(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) → None
- img:表示输入的图像;
- pt1:表示线段的起始点;
- pt2:表示线段的结束点;
- color:表示线条颜色(BGR)或亮度(灰度图像,grayscale image);
- thickness:表示组成矩形的线条的粗细程度;
- line_type:表示线条的类型;
- shift:表示点坐标中的小数点位数。
6、画多边形
在OpenCV中,函数polylines用来画多边形,函数声明如下:
polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]]) → None
- img:表示输入的图像;
- pts:表示多边形点集;
- isClosed:表示绘制的多段线是否闭合,如果是闭合的,那么函数将从每条曲线的最后一个顶点到其第一个顶点绘制一条直线;
- color:表示多边形的颜色;
- thickness:表示多段线边的厚度;
- line_type:表示线条的类型;
- shift:表示点坐标中的小数位数。
实例代码:
import cv2
import numpy as np
img = cv2.imread("test.jpg")
Pts = np.array([[10,5],[20,30],[70,80],[50,10]], np.int32)
cv2.polylines(img,[Pts],True,(0,0,255),2)
cv2.imshow("res", img);
cv2.waitKey(0);
cv2.destroyAllWindows()
运行效果:
7、填充多边形
在OpenCV中,除了绘制多边形之外,还可以填充多边形。函数fillPoly用来填充多边形,函数声明如下:
fillPoly(img, pts, color[, lineType[, shift[, offset]]]) → None
- img:表示输入的图像;
- pts:表示多边形点集;
- color:表示多边形的颜色;
- lineType:表示线条的类型;
- shift:表示点坐标中的小数位数。
- offset:表示等高线所有点的偏移。
代码实例:
import numpy as np
import cv2 as cv
a = cv.imread("test.jpg")
# [10,30] [40,80] [10,90] 为填充的轮廓坐标
triangle = np.array([ [10,30], [40,80], [10,90] ], np.int32)
# (255,0,0) BGR形似表示蓝色
cv.fillPoly(a, [triangle],(255,0,0))
cv.imshow("result", a)
cv.waitKey(0)
运行效果:
三、文字绘制
1、cv.putText()
OpenCV中除了提供绘制各种图形的函数外,还提供了一个特殊的绘制函数,即在图像上绘制文字。这个函数是putText(),它是命名空间cv2中的函数,函数声明如下:
putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]) → None
- img:表示待绘制的图像;
- text:表示待绘制的文字;
- org:表示文本框的左下角;
- fontFace:表示字体;
- fontScale:表示尺寸因子,值越大文字越大;
- color:字体的颜色(RGB);
- thickness:表示线条的宽度;
- lineType:表示线型(4邻域或8邻域,默认8邻域);
- bottmoLeftOrigin:如果为True,那么图像数据原点位于左下角,否则位于左上角。
2、cv.getTextSize()
getTextSize函数获取一个文字的宽度和高度,函数声明如下:
getTextSize(text, fontFace, fontScale, thickness) → retval, baseLine
- text:表示输入的文本文字;
- fontFace:表示文字字体类型;
- fontScale:表示字体缩放系数;
- thickness:表示字体笔画线宽;
- baseLine:是一个返回值,表示文字最底部的y坐标。
绘制文字实例代码:
import cv2
import numpy as np
img = np.zeros([512, 512, 3], dtype=np.uint8)
for i in range(512):
for j in range(512):
img[i, j, :] = [i % 256, j % 256, (i + j) % 256]
info = 'Hello World'
font_face = cv2.FONT_HERSHEY_COMPLEX
font_scale = 2
thickness = 2
text_size = cv2.getTextSize(info, font_face, font_scale, thickness)
print(text_size)
p_center = (int(512 / 2 - text_size[0][0] / 2), int(512 / 2 - text_size[0][1] / 2))
cv2.putText(img, info, p_center, font_face, font_scale, (255,255,255), thickness)
cv2.imshow('res', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行效果:
四、为图像添加边框
在OpenCV中,可以使用函数copyMakeBorder为图像设置边界。该函数可以为图像定义额外的填充(边框),原始边缘的行或列被复制到额外的边框中。该函数声明如下:
cv.copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]]) -> dst
- src:输入的图像,即原图像;
- top、bottom、left、right:分别表示在原图像的4个方向上填充多少像素;
- borderType:表示边界类型。
- value:默认值为0,当borderType取纸为BORDER_CONSTANT时,这个参数表示边界值;
- dst:表示输出图像,和原图像有一样的深度,大小为Size(src.cols + left + right,src.rows + top + bottom)。
具体见参考书83、84页...
五、在图像中查找轮廓
OpenCV中使用findContours函数,通过简单的几个步骤就可以检测出物体的轮廓,很方便。该函数声明如下:
cv.findContours( image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy
- image:表示单通道图像矩阵,可以时灰度图,更常用二值图像;
- mode:表示轮廓检索模式;
- method:表示轮廓近似法;
- contours:是一个向量,并且是双重向量,向量内每个元素保存了一组由连续的Point构成的点的集合向量,每一组Point点集就是一个轮廓,有多少轮廓,向量contours就有多少元素;
- hierarchy:定义为“vector<Vec4i>hierarchy”。
Vec4i的定义如下:
typedef Vec<int, 4> Vec4i;
method定义轮廓的近似方法,取值如下:
- CV_CHAIN_APPROX_NONE:保存物体边界上所有连续的轮廓点到contours向量内;
- CV_CHAIN_APPROX_SIMPLE:仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留;
- CV_CHAIN_APPROX_TC89_L1或CV_CHAIN_APPROX_TC89_KCOS:使用teh-Chinl chain近似算法。
绘制轮廓函数drawContours经常和查找轮廓函数findContours联合使用,查找出轮廓后通常需要把轮廓绘制出来。函数drawContours声明如下:
cv.drawContours( image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]) -> image
- image:表示目标图像;
- contours:表示输入的轮廓组,每一组轮廓由点vector构成;
- contourIdx:指明画第几个轮廓,如果该参数为负值,则画全部轮廓;
- color:轮廓的颜色;
- hierarchy:为轮廓的结构信息;
- maxLevel:表示绘制轮廓的最高级别,只有在hierarchy有效的时候才有效,值为0时,绘制与输入轮廓属于同一等级的所有轮廓(输入轮廓和与其相邻的轮廓),值为1时,绘制与输入轮廓同一等级的所有轮廓与其子节点,值为2时,绘制与输入轮廓同一等级的所有轮廓与其子节点以及子节点的子节点;
- offset:表示可选的轮廓偏移参数。
代码实例:
import cv2
img = cv2.imread("test2.jpg")
# 转换为灰度图
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 再转换为二值图
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
# img:目标图像; contours:轮廓组;contourIdx = -1,表示全部轮廓;
# 轮廓颜色(0,0,255)红色; 轮廓线宽为2
cv2.drawContours(img,contours,-1,(0,0,255),3)
cv2.imshow("img", img)
cv2.waitKey(0)
运行效果图: