Advertisement

OpenCV图像处理技术之图像轮廓

阅读量:

**

©

Fu Xianjun. All Rights Reserved.所有素材来自于小傅老师。**

今天的学习内容俩有点多哦,大家拿起小板凳做好笔记呀!

任务一 轮廓的查找与绘制

案例一 查找轮廓

mode:

cv2.RETR_EXTERNAL 只检测外轮廓

cv2.RETR_LIST检测的轮廓不建立等级关系

cv2.RETR_CCOMP建立两个等级的轮廓

cv2.RETR_TREE建立一个等级树结构的轮廓

method:

cv2.CHAIN_APPROX_NONE存储所有的轮廓点

通过cv2库中的CHAIN_APPROX_SIMPLE参数实现水平、垂直及对角线三个方向元素的压缩,并仅记录每个方向上的最终端点坐标。例如,在矩形轮廓中仅需四个关键点即可完整表示其边界。

导入OpenCV库进行图像处理
使用numpy库辅助运算
通过cv函数读取并加载待处理的图像文件
调用cvtColor函数将BGR格式转换为单色灰度图
应用全局二值化方法提取目标物体的形状特征
利用findContours算法提取图像中的所有连续边界区域及其层次信息
计算并输出所有检测到的目标物体的数量及其各自所占像素点的数量

案例二 绘制轮廓

使用cv2.imshow函数呈现原图像
生成带有具体轮廓的图像,并根据给定的颜色(BGR颜色通道值为0)填充这些轮廓
使用cv2.imshow函数呈现生成后的结果
执行等待键盘输入操作
关闭所有OpenCV窗口

思考:如果要逐个绘制一幅图像内的边缘信息,应该怎么做?

n等于contours的数量 #表示轮廓的数量
初始化一个空列表contoursImg=[]
遍历所有轮廓索引i from 0到n-1
创建一个与原图像相同大小的全黑图像temp=np.zeros(img.shape,np.uint8)
将第i个图像赋值为绘制第i个轮廓后的结果contoursImg[i]=cv2.drawContours(temp,contours,i,(255,255,255), 3)
显示第i个绘制好的轮廓图cv2.imshow("contours[" + str(i)+"]",temp)
等待用户按下任意键执行操作cv2.waitKey()
关闭所有显示窗口cv2.destroyAllWindows()

练习一下吧:实物轮廓检测

导入OpenCV库
读取图片文件pig.jpg为变量img
显示图片img
将读取的BGR格式图像转换为灰度图并存储在变量gray中
对灰度图gray应用二值化处理:当像素值大于等于245时设为白色(即255),其余设为黑色(即0),并存储结果于binary变量中
显示二值化后的图像binary
利用binary提取轮廓信息,并将这些轮廓绘制到全白背景mask上
显示掩膜图像mask
对原始图像img与掩膜mask进行按位与操作得到最终结果result
显示处理后得到的结果图像result
等待按键后再关闭所有OpenCV窗口

任务二 使用矩特征计算轮廓的面积及长度

案例一 计算图像的矩特征

import cv2
import numpy as np
img = cv2.imread('shape.jpg') #读取图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度值图
ret, binary = cv2.threshold(gray,220,255,cv2.THRESH_BINARY) #转为二值图
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,\
cv2.CHAIN_APPROX_NONE) #寻找轮廓
n=len(contours) #轮廓个数
contoursImg=[]
for i in range(n):
temp=np.zeros(img.shape,np.uint8) #生成黑背景
contoursImg.append(temp)
contoursImg[i]=cv2.drawContours(contoursImg[i],contours,i,(255,255,255), 3) #绘制轮廓
cv2.imshow("contours[" + str(i)+"]",contoursImg[i]) #显示轮廓
print("计算图像的矩特征:")
for i in range(n):
moment=cv2.moments(contours[i])
print(f"轮廓{i}的矩:\n{moment}")
cv2.waitKey()
cv2.destroyAllWindows()

计算面积

for i in range(n):
area=cv2.moments(contours[i])["m00"]
print(f"轮廓{i}的面积:\n{area}")

案例二 计算轮廓面积

import cv2
import numpy as np
img = cv2.imread('shape.jpg') #读取图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度值图
ret, binary = cv2.threshold(gray,220,255,cv2.THRESH_BINARY) #转为二值图
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,\
cv2.CHAIN_APPROX_NONE) #寻找轮廓
n=len(contours) #轮廓个数
contoursImg=[]
for i in range(n):
area = cv2.contourArea(contours[i])
print(f"轮廓{i}的面积:\n{area}")

练习:显示面积小于20000的轮廓

遍历i从0到n-1的每个值:
计算第i个轮廓的面积并将其存储于变量area中:
输出第i个轮廓及其面积信息:
如果某个区域的面积小于2万像素,则执行以下操作:
创建一个与原图像尺寸相同的黑色背景图像:
将该黑色背景添加到contoursImg列表中:
绘制第i个轮廓到当前图像中:
在OpenCV窗口中显示第i个区域的处理结果:
等待用户按任意键后退出程序:

案例三 计算轮廓长度

n = len(contours) # 计算轮廓数量
contours_img = [] # 初始化轮廓图像列表
for i in range(n):
length = cv2.arcLength(contours[i], True) # 计算第i+1个轮廓的长度
print(f"第{i+1}个轮廓的长度为:\n{length}")

任务三 使用Hu特征进行形状匹配

案例一:形状匹配

导入cv2模块
o1为cv2读取m1.png文件中的图像
o2为cv2读取m2.png文件中的图像
o3为cv2读取m3.png文件中的图像
gray1为使用BGR转灰度图的转换函数读取o1的灰度图像
gray2为使用BGR转灰度图的转换函数读取o2的灰度图像
gray3为使用BGR转灰度图的转换函数读取o3的灰度图像
ret以及binary变量分别为使用阈值二值化方法处理gray变量后的结果
contours变量通过findContours方法获取目标图像轮廓信息
cnt变量存储contours列表中的第一个轮廓数据集
ret0至ret3分别用于计算不同形状之间的匹配程度
打印相同形状匹配结果、相似形状匹配结果以及不相似形状匹配结果的具体数值信息

自主探索:判断阮经天和彭于晏谁跟明道更像。

导入OpenCV模块
读取图片文件并存储在变量o1中
读取另一张图片文件并存储在变量o2中
读取第三张图片文件并存储在变量o3中
将bgr图像转换为灰度图并赋值给gray1变量
将另一张bgr图像转换为灰度图并赋值给gray2变量
将第三张bgr图像转换为灰度图并赋值给gray3变量
对第一张灰度图应用阈值分割得到binary1变量
对第二张灰度图应用阈值分割得到binary2变量
对第三张灰度图应用阈值分割得到binary3变量
查找第一张二值化图像的所有轮廓及其层次信息并赋值给contours1和hierarchy变量
查找第二张二值化图像的所有轮廓及其层次信息并赋值给contours2和hierarchy变量
查找第三张二值化图像的所有轮廓及其层次信息并赋值给contours3和hierarchy变量
获取第一个轮廓边界信息存入cnt1变量中
获取第二个轮廓边界信息存入cnt2变量中
获取第三个轮廓边界信息存入cnt3变量中
计算第一个与第一个轮廓的匹配程度并将结果存储于ret0中
计算第一个与第二个轮廓的匹配程度并将结果存储于ret1中
计算第一个与第三个轮廓的匹配程度并将结果存储于ret2中
输出相同类型图像的匹配程度
输出相似类型图像的匹配程度
输出不同类型的图像匹配程度

任务四 轮廓拟合

案例一:矩形包围框

import cv2
读取图像 img = 导入OpenCV库并使用 imread 函数加载图片 'shape.jpg'
显示原始图像 cvtshow 显示变量名 'original' 和 图像对象 img
将彩色图像 转换为灰度图 gray = 使用 OpenCV 的 COLOR_BGR2GRAY 转换通道参数
执行阈值二值化 ret, binary = 使用 OpenCV 的 threshold 方法对灰度图进行阈值处理
提取轮廓信息 contours, hierarchy = 使用 OpenCV 的 findContours 方法提取轮廓及其层次结构信息
获取边界框坐标 x,y,w,h = 使用 OpenCV 的 boundingRect 函数获取第一个轮廓的最小包围矩形参数
绘制矩形边界框 在图像对象 img 上使用 OpenCV 的 rectangle 方法绘制从 (x,y) 到 (x+w,y+h) 的黑色矩形边框宽度 1 像素
显示结果图像 cvtshow 显示变量名 'result' 和 图像对象 img
等待键盘事件 使用 OpenCV 的 waitKey 方法等待键盘输入并返回一个整数值
关闭所有OpenCV窗口 使用 OpenCV 的 destroyAllWindows 方法关闭当前窗口

案例二:最小包围矩形框

import cvt
o = cvt.imread("shape.jpg")
cvtColor o to grayscale using OpenCV function
convert the gray image to binary threshold with OpenCV function
find contours in the binary image using OpenCV findContours function
determine the minimum area rectangle of the contour using OpenCV minAreaRect function
print the result of minAreaRect
get the four corner points of the rectangle using OpenCV boxPoints function
convert points to integer type using numpy int64 function
draw the contour on original image with black color and thickness 1 pixel using OpenCV drawContours function
display the processed image with title "result" in a new window using OpenCV imshow function
wait for key press and then close all OpenCV windows

案例三:最小包围圆形

导入OpenCV库
使用cv\texttt{cv}模块读取图片到变量o中
显示名为'original'的图像到窗口中
将图像转换为灰度并存储在变量gray中
应用二值化阈值处理得到binary掩膜
利用findContours方法提取轮廓信息并返回其层次关系

(x,y), radius = cv2.minEnclosingCircle(contours[1])
center = (int(x), int(y))
radius = int(radius)
cv2.circle(o, center, radius, (0, 0, 0), 2) # 类似于 Matplotlib 的绘图方式
cv2.imshow("result", o)
cv2.waitKey()
cv2.destroyAllWindows()

案例四:最优拟合椭圆

导入OpenCV模块
使用OpenCV模块读取图片
显示原始图像窗口
将图像转换为灰度并存储在变量gray中
根据阈值生成二值化图像
提取二值化图像的所有轮廓及其层次信息
使用简化方法获取轮廓边界

通过OpenCV拟合得到一个椭圆参数,并将其存储在变量ellipse中。
显示计算得到的椭圆参数。
以绿色(RGB值为(0, 255, 0))绘制指定大小的椭圆。
在名为'result'的窗口中显示图像。
等待键盘输入并结束所有OpenCV操作。

案例五:最优拟合直线

import cv
o= cv.readImage("shape.jpg")
展示原始图像 o
将图像转换为灰度图 gray
生成二值化图像 ret binary
提取轮廓 contours hierarchy 使用列表法提取并简化轮廓

rows和cols分别取自o.shape的前两项。
[vx, vy, x, y]被赋值为cv2.fitLine函数的结果参数。
lefty被计算为(-x*vy)/vx + y的一个整数值。
righty则基于(cols - x)乘以vy再除以vx再加上y得到。
随后绘制从(o.cols-1,righty)到(0,lefty)的一条绿色线条。
最后展示图像并等待用户操作后退出程序。

案例六:逼近多边形

import cv2
import numpy as np

多边形逼近

1.首先确定轮廓边界

img = cv2.imread('contours3.png')
cv2.imshow("original", img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
current_contour = contours[0]

2. 通过多边形逼近技术进而获得目标图形的角点坐标

通过调整参数使得多边形逼近达到预期效果
适当缩小误差范围能够使结果更为精确
适当放大误差范围则能捕捉到更多细节信息

3.画出多边形

adp=img.copy()
img1=cv2.polylines(adp, [approx1], True, (255, 0, 0), 2)
cv2.imshow('approxPloyDP1', img1)

adp=img.copy()
img2=cv2.polylines(adp, [approx2], True, (0, 255, 0), 2)
cv2.imshow('approxPloyDP2', img2)

adp=img.copy()
img3=cv2.polylines(adp, [approx3], True, (0, 0, 255), 2)
cv2.imshow('approxPloyDP3', img3)

print(len(approx1),len(approx2),len(approx3)) # 角点的个数

cv2.waitKey(0)
cv2.destroyAllWindows()

注意哈!今天有任务噢!

使用所学知识,仅绘制hand.png的手掌多边形轮廓

我们下期在再见!拜拜!

全部评论 (0)

还没有任何评论哟~