文章目录
1. 尺寸调整
1.1 函数简述和原型
通过该函数可以对图像进行放大或缩小处理。官方文档:https://docs.opencv.org/3.4.2/da/d54/group__imgproc__transform.html#ga47a974309e9102f5f08231edc7e7529d
dst = cv2.resize(src, dsize[, fx[, fy[, interpolation]]])
1.2 参数
- src:要处理的图像数据;
- dsize:目的大小,一个二元元组,分别为处理后图像的宽和高,即(width, height);
- fx:x方向(宽度方向)缩放的倍数,当dsize不为None时,其值必须为目标图像宽度/原图像宽度;
- fy:y方向(高度方向)缩放的倍数,当dsize不为None时,其值必须为目标图像宽度/原图像宽度;
- interpolation:插值方法flag,常用的有如下几种:
- cv2.INTER_AREA:重采样插值法,常在缩小图片时使用;
- cv2.INTER_CUBIC:双三次插值法,常在放大图片时使用,质量较好但速度较慢;
- cv2.INTER_LINEAR:双线性插值法,常在放大图片时使用,质量一般但速度较快;
1.3 返回值
- dst:返回的即为缩放后的图片数据;
1.4 用法举例
img = cv2.imread(r".\image.jpg", cv2.IMREAD_COLOR)
# 缩小图片,仅使用dsize参数
shrinkImg = cv2.resize(img, (int(cols/2), int(rows/2)), interpolation=cv2.INTER_AREA)
# 放大图片,x方向(宽度)和y方向(高度)均放大两倍,使用fx和fy参数,则dsize参数必须为None
enlargeImg = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)
2. 图像二值化
2.1 函数简述和原型
通过该函数可以对图像进行二值化处理,处理后的图片非黑即白,这是一种非常常用的图像处理手段。官方文档:https://docs.opencv.org/3.4.2/d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57
retval, dst = cv2.threshold(src, thresh, maxval, type)
2.2 参数
- src:要处理的图像数据,为单通道灰度图像;
- thresh:double类型,阈值;
- maxval:double类型,二值化后的最大值,仅在cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV两种二值化时有用;
- type:二值化类型flags,常用的有如下几种:
- cv2.THRESH_BINARY:像素灰度值大于阈值时,取最大值,否则取0(黑色)。主要用于提取高亮部分,但所有细节均丢失;
- cv2.THRESH_BINARY_INV:像素灰度值大于阈值时,取0(黑色),否则取最大值,实际上就是THRESH_BINARY取反的效果。主要用于提取暗部,但所有细节丢失;
- cv2.THRESH_TRUNC:像素灰度值大于阈值时,直接减小到阈值,其余部分不变,即仅将高亮部分丢失所有细节;
- cv2.THRESH_TOZERO:像素灰度值未超过阈值时直接取0(黑色),超过阈值的保留原值,即仅保留高亮部分所有细节;
- cv2.THRESH_TOZERO_INV:像素灰度值超过阈值的直接取0,未超过阈值的保留原值,即仅保留低于阈值部分所有细节,直接抹黑高亮,类似cv2.THRESH_TRUNC,但抹平高亮部分比trunk更厉害;
- cv2.THRESH_OTSU:二值化时阈值往往需要通过经验来判断,但还有一种OSTU方法,可以寻找最佳的阈值。以上各种二值化方法直接加上该flag即表示阈值通过OSTU法自动计算;
2.3 返回值
- retval:布尔类型,是否成功二值化处理图像;
- dst:二值化后的图片数据;
2.4 用法举例
img = cv2.imread(r'.\image.jpg', cv2.IMREAD_GRAYSCALE)
# 直接简单二值阈值分割,灰度小于等于127则为0(纯黑色),大于127则为255(纯白色)
ret1, thBi = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# Otsu法(大津法——最大类间方差法)计算全局最佳阈值,因此第二个参数可以忽略
ret2, thOtsu = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
2.5 实例展示
下图展示了几种不同的二值化类型的差异,均以127为阈值,最大值均为255(白色):
3. 图像自适应二值化
3.1 函数简述和原型
该函数是上述二值化函数的改进版。很多时候一张灰度图像的亮度并不是在各处都一致,因此在使用上述函数进行二值化时,即使使用OSTU法,计算出来的二值化阈值也不一定在一副图像的不同区域都是最佳的。因此OpenCV还提供了自适应的二值化函数,通过该函数可以对图像的不同区域动态计算并应用不同的阈值进行二值化。官方文档:https://docs.opencv.org/3.4.2/d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3
dst = cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
3.2 参数
- src:要处理的图像数据,为单通道灰度图像;
- maxValue:double类型,二值化后的最大值;
- adaptiveMethod:动态计算阈值的方法,有以下两种:
- cv2.ADAPTIVE_THRESH_MEAN_C:计算区域内的平均值减去C;
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C:计算区域内的高斯均值减去C;
- thresholdType:二值化类型flags,在该函数中仅能使用cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV两种
- blockSize:动态化计算阈值时所使用的区域的大小,类似卷积时的卷积核大小,需要为奇数;
- C:计算区域内的均值后减去的常量,最后作为阈值;
3.3 返回值
- dst:二值化后的图片数据;
3.4 用法举例
img = cv2.imread(r'.\image.jpg', cv2.IMREAD_GRAYSCALE)
# 计算11*11区域内的均值,再减去4(最后一个参数C)作为阈值
th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY, 11, 4)
# 计算17*17区域内的高斯均值,再减去6(最后一个参数C)作为阈值
th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 17, 6)
3.5 实例展示
对比简单二值化和自适应二值化对某张图像的应用如下:
4. 图像绘制
4.1 函数简述和原型
OpenCV提供了一系列图像绘制的API,可以在图像上进行各种基本绘制,如绘制直线、箭头、各种形状、添加文字等。官方文档:https://docs.opencv.org/3.4.2/d6/d6e/group__imgproc__draw.html
# 在图片上绘制直线
cv2.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]])
# 在图片上绘制箭头
cv2.arrowedLine(img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]])
# 在图片上绘制一个直立的矩形(即没有任何旋转)
cv2.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]])
# 在图片上绘制圆形
cv2.circle(img, center, radius, color[, thickness[, lineType[, shift]]])
# 根据圆心、长轴长度、长轴方向、弧长夹角在图片上绘制部分椭圆
cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]])
# 在图片上绘制某个矩形的内切椭圆
cv2.ellipse(img, box, color[, thickness[, lineType]])
# 绘制多条线段,可以闭合形成多边形
cv2.polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]])
# 绘制一个实心的多边形
cv2.fillPoly(img, pts, color[, lineType[, shift[, offset]]])
# 在图片上添加文字
cv2.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]])
4.2 参数
- img:要进行绘制的图像;
- pt1, pt2:在绘制直线、箭头时,二者分别表示起点坐标和终点坐标;在绘制直立矩形时,二者分别表示矩形左上角和右下角的坐标位置;
- tipLength:double类型,默认值为0.1,表示箭头相对于箭头直线长度的大小比例;
- center:一个二元组,在绘制圆形和椭圆形时,表示圆心的坐标;
- radius:int类型,绘制圆形时表示圆的半径;
- axes:一个二元组,绘制部分椭圆形时分别表示椭圆在水平和竖直方向上的轴的长度,两个轴较大的为长轴,旋转后两个轴也不一定与x轴和y轴平行;
- angle:double类型,绘制部分椭圆时表示椭圆的旋转角度,顺时针方向;
- startAngle,endAngle:double类型,绘制部分椭圆时分别表示弧的起始位置/终止位置与圆心连线相对于(旋转前)水平方向轴的夹角,顺时针方向,当
startAngle=0, endAngle=360
时则表示将整个椭圆绘制出来; - box:绘制椭圆时的外切矩形,不一定是直立的矩形。可以通过一个三元组定义出来,元素分别为矩形中心坐标(二元组)、矩形宽高(二元组)、矩形顺时针旋转角度(float);
- pts:使用
polylines
函数绘制多条线段时,各个顶点的坐标,一个n*2的矩阵;使用fillPloly
绘制填充多边形时,由于可以同时填充多个多边形,故需要是一个list,每个元素为一个n*2的矩阵(表示一个n边形); - isClosed:bool类型,绘制多条线段时是否闭合形成多边形;
- offset:一个二元组,在绘制填充多边形时表示所有多边形在x方向和y方向平移的距离,默认为(0,0);
- text:要添加的文本内容,字符串;
- org:一个二元组,表示文本左下角所在位置的坐标;
- fontFace:字体类型,常用有如下几种:
- cv2.FONT_HERSHEY_SIMPLEX:普通字体;
- cv2.FONT_HERSHEY_PLAIN:小号字体;
- cv2.FONT_HERSHEY_SCRIPT_SIMPLEX:手写体;
- fontScale:double类型,字体大小;
- bottomLeftOrigin:bool类型,默认值为false,表示是否以图片左下角作为原点;
- color:颜色,对于单通道灰度图像,为一个0-255之间的值;对于BGR彩色图像,则为一个三元组,值分别为蓝色、绿色和红色的分量;
- thickness:int类型,默认值为1,表示绘制线段的宽度,若为负数,如cv2.FILLED时,表示填充要绘制的形状。注意使用
polylines
绘制多边形时无法填充,填充多边形必须使用fillPoly
函数; - lineType:线段的类型,当
thickness=cv2.FILLED
时,该参数往往忽略。主要由以下几种类型:- cv2.LINE_4:表示线段为4邻接线段;
- cv2.LINE_8:表示线段为8邻接线段;
- cv2.LINE_AA:表示线段为抗锯齿(antialiased)绘制;
- shift:int类型,默认值为0,各种坐标中小数的位数,往往不需要设置(坐标常常均以像素为单位,为整数);
4.3 返回值
上述函数均是对图像进行原地修改的函数,故返回值为None。
4.4 用法举例
# 创建一个500*500的黑色画布
canvas = np.zeros((500, 500, 3), dtype=np.uint8)
# 绘制一条红色直线
cv2.line(canvas, (50, 50), (200, 50), color=(0, 0, 255), thickness=2, lineType=cv2.LINE_AA)
# 绘制一个黄色箭头
cv2.arrowedLine(canvas, (250, 50), (450, 50), color=(0, 255, 255), thickness=2, line_type=cv2.LINE_AA, tipLength=0.3)
# 绘制一个白色矩形
cv2.rectangle(canvas, (50, 100), (200, 150), color=(255, 255, 255), thickness=2, lineType=cv2.LINE_AA)
# 绘制一个填充蓝色的圆形
cv2.circle(canvas, (300, 125), 50, color=(255, 0, 0), thickness=cv2.FILLED)
# 绘制一个绿色椭圆形的上半部分
cv2.ellipse(canvas, (125, 220), (25, 50), 0, 180, 360, color=(0, 255, 0), thickness=3, lineType=cv2.LINE_AA)
# 在图片上绘制某个矩形的内切椭圆
box = ((350, 220), (100, 50), 45.0)
cv2.ellipse(canvas, box, color=(0, 0, 255), thickness=3, lineType=cv2.LINE_AA)
# 绘制一个黄色的六边形
center_x = 125
center_y = 330
pts = np.array([[center_x, center_y - 60], [center_x + 52, center_y - 30],
[center_x + 52, center_y + 30], [center_x, center_y + 60],
[center_x - 52, center_y + 30], [center_x - 52, center_y - 30]], np.int32)
cv2.polylines(canvas, pts=[pts], isClosed=True, color=(0, 255, 255), thickness=5, lineType=cv2.LINE_AA)
# 绘制两个红色的实心六边形
center_x = 300
center_y = 330
pts1 = np.array([[center_x, center_y - 60], [center_x + 52, center_y - 30],
[center_x + 52, center_y + 30], [center_x, center_y + 60],
[center_x - 52, center_y + 30], [center_x - 52, center_y - 30]], np.int32)
center_x = 420
center_y = 330
pts2 = np.array([[center_x, center_y - 60], [center_x + 52, center_y - 30],
[center_x + 52, center_y + 30], [center_x, center_y + 60],
[center_x - 52, center_y + 30], [center_x - 52, center_y - 30]], np.int32)
cv2.fillPoly(canvas, [pts1, pts2], color=(0, 0, 255), lineType=cv2.LINE_AA)
# 在图片上添加文字
cv2.putText(canvas, "Hello OpenCV!", (30, 470), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=2, color=(255, 255, 255), thickness=2, lineType=cv2.LINE_AA)
cv2.imshow('drawing', canvas)
4.5 实例展示
上述代码的输出如下图: