发现你的身形——OpenCV图像轮廓

写在最前

我的意思不是说你长得很胖,emmmm,而是你的轮廓很大。
——五星上将詹姆斯下士如是说

妹子 胸大
果然有图没图,理解是不一样的,这就体现了计算机视觉的重要性,2333
上一节最后,我们说过这一次我们就将会讲解真正的OpenCV图像轮廓有关知识。轮廓发现的具体实现有多种方式,不过其实其使用在OpenCV中的使用并不困难,不过想用好还需要多点基础知识。所以这里我们会首先讲一讲OpenCV中的轮廓发现算法,然后再讲一讲其他可以用于轮廓发现的特殊方法。这里我们主要使用了两种来自于opencv官方的图片(Note:上面那张不是),第一张是彩色快乐鱼,第二张是水果分尸图不对,应该是果缤纷才对。\(^o^)/~

鱼

轮廓发现算法

opencv中的轮廓发现算法来自于1985的一篇论文《TopologicalStructural Analysis of Digitized Binary Images by Border Following》,这篇论文主要讲了两种可有效利用于轮廓发现的边界跟踪算法,其中第一种是区分二值图像边界之间的保卫关系(surroundness relations)第二种是第一种算法的变形,只跟踪最外层轮廓。对于具体内容这里不再过多描述,你可以自行查阅。至于具体的使用,我们直接使用OpenCV中的函数findContours即可。

由于opencv中的轮廓发现借鉴于论文《 Analysis of Digitized Binary Images by Border Following》,所以其只能接受二值化之后的图像,也就是说我们需要先对原始图像进行二值化处理,这里需要使用函数cvtColor将图片进行类型转化,具体代码如下:

# 灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
ret, binary = cv2.threshold(gray, 175, 255, cv2.THRESH_BINARY)

其中COLOR_BGR2GRAY的作用一如其名,就是将BGR图像转化为GRAY(灰度图,又名遗照)

灰度图 鱼

之后我们就可以使用 cv2.threshold方法进行二值化处理,就这样一条彩色的快乐鱼就变成了一张黑白的快乐鱼遗照了。其中要注意的是,阈值是由我们自己选定的(这里是175),我们也可以通过修改阈值来获取新的二值化参数。

鱼 二值化

最终,我们就可以将二值化之后的图像传进轮廓发现算法,进行轮廓发现并绘制。代码与结果如下:

# 轮廓发现
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 轮廓绘制
cv2.drawContours(img, contours_new, -1, (0, 0, 255), 3)

鱼 轮廓图

现在快乐鱼就被惨遭“分尸”了,嘴巴上多了一条大口子。而说回正事,上面的代码中drawContours函数就是绘制函数,第一个参数是需要绘制的原图像,第二个参数是之前我们使用算法发现的轮廓,第三个参数则表示绘制的轮廓索引,这里使用-1表示绘制所有轮廓,第四个参数则是绘制轮廓时线条的颜色,这里我们选择红色0。第五个参数则表示线条粗细度,如果是负值则在轮廓内部绘制。除此之外还有一个隐身的六娃lineType表示线条类型,因为有默认数值LINE_8,所以这里没有设置。

不过除了这些基本的操作外,我们还可以有很多其他的操作,比如借助之前我们学过的滤波函数对图像进行处理,去除那些意义不大的小色块,或者使用边缘检测算法如Canny先一步获取图形边缘(代替直接二值化哪一步),然后再进行轮廓发现,这些操作避免发现错误轮廓,同时我们也可以使用判断方法选择一定周长或者面积的轮廓。前者直接使用cv.blur(src_gray, (3,3)),以及函数canny_output = cv.Canny(gray, threshold, threshold * 2)即可,后者则需要几个opencv的函数进行配合,具体代码如下:

# Detect edges using Canny
threshold = 100
# Detect edges using Canny
canny_output = cv2.Canny(gray, threshold, threshold * 2)
for i in range(len(contours)):
    # 计算轮廓所包含的面积
    area = cv2.contourArea(contours[i])
    # 计算轮廓的周长
    perimeter = cv2.arcLength(contours[i], True)
    
    if perimeter >= 10 and area >= 20:
        print("第{0}个轮廓的面积为{1},周长为{2}".format(i+1,area,perimeter))
        contours_new.append(contours[i])

边缘检测 鱼

鱼 绘制轮廓

第一段代码的作用是使用Canny进行边缘检测(展示的图片也经过了均值模糊),然后得到一张只有边缘数据的图,这样就避免了之前直接二值化产生的像素阈值产生的本来不存在的误差,而第二行代码则是利用计算轮廓面积和计算轮廓周长的函数进行轮廓筛选。其实这里我们也可以选择不进行筛选直接进行获取,但是在一般情况下

均值模糊,边缘检测,周长,面积等都是十分有用的操作,至于怎么用则需要根据实际情况进行调整。

边缘检测

这里还提到了边缘检测,边缘检测顾名思义就是检测图片的边缘。在一些特殊情况下其实边缘检测比直接轮廓获取有用,不过也有些时候图像分割的一些技术更有用一些。这几项技术的特点都是作用于图像中的区域对其进行处理。只不过在没有深度学习的时代,没有像目标检测,或者现代的更直接的自动进行图像分割的技术,只能使用各类算法进行手动操作,从不同的图片中手动设置不同的方法获取我们想要的信息。

Canny就是一种比较常见的边缘检测方法,下面就是一个例子。我们将会在下一届仔细的讲讲的边缘检测等有关图像处理技术。

水果,OpenCV
水果 边缘检测 OpenCV

写在最后

大概写到这个时候感觉确实可以出个专栏了,所以正式规划了《漫谈计算机视觉》,频率大概会一周一更,大概会从OpenCV将其,然后一直串到这两年各个计算机视觉领域比较经典深度神经网络。同时代码会开源,之后代码和有关数据前往FontTian的Github下载即可,包括之前的内容都会穿上去,项目位置在这:https://github.com/FontTian/Gossipage_About_CV。

OpenCV图像轮廓是指在图像中连续的边界线。根据引用中的示例代码,我们可以使用OpenCV库来实现图像轮廓的查找和计算。 首先,我们需要读取图像并将其转换为灰度图像。可以使用cv2.imread()函数读取图像,然后使用cv2.cvtColor()函数将图像转换为灰度图像。 接下来,我们可以使用cv2.threshold()函数将灰度图像二值化,得到一个二值图像,其中只有两个像素值,一种是白色(255),一种是黑色(0)。函数中的阈值参数可以根据具体应用进行调整。 然后,我们可以使用cv2.findContours()函数查找图像中的轮廓。该函数返回两个结果,第一个结果是轮廓的列表,第二个结果是层级信息。轮廓是一系列坐标点的集合,描述了对象的边界。 接着,我们可以使用cv2.drawContours()函数将轮廓绘制在图像上。这个函数会直接修改原图像,如果想保持原图像不变,可以先复制一份。通过指定轮廓的索引,我们可以绘制特定的轮廓。 最后,我们可以使用cv2.contourArea()函数计算轮廓的面积,使用cv2.arcLength()函数计算轮廓的周长。这两个函数都需要传入一个轮廓参数。 所以,OpenCV图像轮廓的实现步骤可以总结为以下几个步骤: 1. 读取图像并将其转换为灰度图像。 2. 使用阈值函数将灰度图像二值化。 3. 使用findContours函数查找图像中的轮廓。 4. 绘制轮廓在图像上。 5. 计算轮廓的面积和周长。 希望这个回答能帮到你!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [opencv 图像轮廓的实现示例](https://download.csdn.net/download/weixin_38681736/12849896)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [OpenCv图像轮廓](https://blog.csdn.net/weixin_64443786/article/details/131796588)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Font Tian

写的很好,请给我钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值