opencv 去除孤立点以及findContours()和connectedComponentsWithStats()详解

findContours()和connectedComponentsWithStats()两个函数可以分别实现去除图像孤立点的功能

connectedComponentsWithStats()函数原理是检测像素的连通区域(连通图应该不用介绍-.-),上图中每个白色斑点区域都属于一个个连通区域,当然文字部分也是,通过这个函数检测到每个连通区域后,再对不同区域的面积进行筛选(孤立点的面积肯定远远小于文字的面积),就可以去掉这些孤立点,函数用法如下:

num_labels, labels, stats, centroids = cv.connectedComponentsWithStats(src, connectivity=8, ltype=None)

函数参数:

src:传入需要处理的图片,要求为二值图像,上面用例的图像已经是二值图像了,如果不是的话需要加一步二值化

connectivity:可选值为4或8,也就是使用4连通还是8连通,就是这个区别,简单易懂

 ltype:这个参数跟输出有关,可以先默认,不用管

返回值:

num_labels:所有连通域的数目
labels:这个返回值很关键,主要就用到这个,ltype参数默认为none的情况下,输出的labels是一个和原图一样大小的矩阵,原图中检测到的连通图的位置,对应的labels矩阵值为1,其余值为0,算是一种特殊的标记
stats:记录了每个连通区域的信息,是一个5列的矩阵,每一行对应一个连通区域,分别为连通区域外接矩形的x、y、width、height和面积,例如stats[0][4]就是第一个连通区域的面积
centroids:连通域的中心点,没什么大用

这样就可以通过stats对连通域进行筛选,再通过labels确定筛选出的区域坐标,在进行各种想进行操作,比如这个去除孤立点,直接让该区域像素值置为背景颜色0,就去掉了

再说findContours()函数

contours, hierarch = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)

这个相对简单一点,是检测输入图像的轮廓,最后同样通过面积进行筛选

函数参数:

img: 输入图像,最好也是二值图像;

第二个: 表示轮廓的检索模式,有四种(有兴趣的朋友可以自己搜一下区别,这里不多做赘述了-.-)

第三个:轮廓的近似办法,有三种(同上)

返回值:

coutours:一个list,list中每个元素都是图像中的一个轮廓信息,用numpy中的ndarray表示,配合cv.contourArea() 函数可以直接得到轮廓面积,配合cv.drawContours()函数可以对某个区域进行操作,比如上述的直接让该区域像素值置为背景颜色0(这俩函数也不多做赘述了,一搜一大堆)

hierarchy:轮廓间的层次关系,为三维数组,形状为(1,n,4),用不上的参数统统简略

两个方法,个人更推荐第一个,连通区域的检测比轮廓检测要精准很多,就是慢点,毕竟有for循环

这是代码,Img1()和Img2()分别对应两个方法:

import cv2.cv2 as cv
import numpy as np

def Img1(src):
    num_labels, labels, stats, centroids = cv.connectedComponentsWithStats(src, connectivity=8, ltype=None)
    img = np.zeros((src.shape[0], src.shape[1]), np.uint8)    #创建个全0的黑背景
    for i in range(1, num_labels):
        mask = labels == i             #这一步是通过labels确定区域位置,让labels信息赋给mask数组,再用mask数组做img数组的索引
        if stats[i][4] > 300:         #300是面积 可以随便调
            img[mask] = 255
                      #面积大于300的区域涂白留下,小于300的涂0抹去
        else:
            img[mask] = 0
           
    return img

def Img2(img):
    contours, hierarch = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
    area = []
    for i in range(len(contours)):
        area.append(cv.contourArea(contours[i]))   #计算轮廓所占面积
        if area[i] < 300:                   #轮廓面积,可以自己随便调
            cv.drawContours(img,[contours[i]],0,0,-1)         #该轮廓区域填0
            continue
    return img

src = cv.imread('01.png',0)
cv.imshow('input',src)
cv.waitKey(0)
src = Img1(src)
cv.imshow('output', src)
cv.waitKey()

  • 15
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
OpenCV是一款广泛应用于计算机视觉和图像处理的库。在处理图像时,有时候我们需要去除图像中的孤立孤立是指与周围像素相差较大且数量较少的像素。下面我将介绍一种使用OpenCV去除孤立的方法。 1. 首先,我们需要读取待处理的图像,并将其转换为灰度图像。可以使用OpenCV的函数`cv::imread()`读取图像,并使用函数`cv::cvtColor()`将其转换为灰度图像。 2. 接下来,我们可以使用OpenCV的函数`cv::inRange()`来对图像应用二值化处理。二值化可以将图像中大部分像素转换为黑色或白色。我们可以将较大的像素值设置为白色,并将较小的像素值设置为黑色。 3. 然后,我们可以使用OpenCV的函数`cv::findContours()`来寻找图像中的轮廓。轮廓是由一系列连续的像素组成的曲线。`cv::findContours()`函数将返回一个存储所有轮廓的向量。 4. 接下来,我们可以遍历这些轮廓,并使用`cv::contourArea()`函数计算每个轮廓的面积。如果轮廓的面积小于一定的阈值,我们可以将其认为是孤立,并使用`cv::drawContours()`函数将其填充为黑色。 5. 最后,我们可以将处理后的图像保存到文件中,使用OpenCV的函数`cv::imwrite()`即可。 通过以上步骤,我们可以使用OpenCV对图像进行处理,去除孤立。当然,具体的阈值和处理方法可以根据实际需求进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值