OpenCV自带寻找轮廓的函数,流程是:获取灰度图→图片二值化→寻找轮廓

直接上代码(Python版)

import cv2

def find_contours(imgname):
    img = cv2.imread(imgname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    cv2.imwrite("gray.jpg", gray)
    _, binary = cv2.threshold(gray, 220, 255, cv2.THRESH_BINARY)
    cv2.imwrite("binary.jpg", binary)
    image, contours, hierarchy = cv2.findContours(
        binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
    )
    cv2.drawContours(img, contours, -1, (0, 0, 255), 3)
    cv2.putText(
        img,
        "{:.3f}".format(len(contours)),
        (30, 30),
        cv2.FONT_HERSHEY_SIMPLEX,
        1.0,
        (0, 255, 0),
        1,
    )
    # cv2.imshow("img", img)
    cv2.imwrite("contours.jpg", img)
    cv2.waitKey(0)


if __name__ == "__main__":
    img = "test.jpg"
    find_contours(img)

函数说明:

(1)cvtColor:将彩色图转为灰度图

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );

//参数解释: 
//InputArray src: 输入图像即要进行颜色空间变换的原图像,可以是Mat类 
//OutputArray dst: 输出图像即进行颜色空间变换后存储图像,也可以Mat类 
//int code: 转换的代码或标识,即在此确定将什么制式的图片转换成什么制式的图片
//int dstCn = 0: 目标图像通道数,如果取值为0,则由src和code决定

(2)threshold:将图像二值化为黑白图片

double cv::threshold(
	cv::InputArray src, // 输入图像
	cv::OutputArray dst, // 输出图像
	double thresh, // 阈值
	double maxValue, // 向上最大值
	int thresholdType // 阈值化操作的类型 
);

(3)findContours:寻找图像中物体的轮廓

void cv::findContours   (   InputOutputArray    image,
                            OutputArrayOfArrays     contours,
                            OutputArray     hierarchy,
                            int     mode,
                            int     method,
                            Point   offset = Point() 
                        )   
//image:输入图像,图像必须为8-bit单通道图像,图像中的非零像素将被视为1,0像素保留其像素值,故加载图像后会自动转换为二值图像。我们同样可以使用
//contours:检测到的轮廓,每个轮廓都是以点向量的形式进行存储即使用point类型的vector表示 
//hierarchy:可选的输出向量(std::vector),包含了图像的拓扑信息,作为轮廓数量的表示hierarchy包含了很多元素,每个轮廓contours[i]对应hierarchy中hierarchy[i][0]~hierarchy[i][3],分别表示后一个轮廓,前一个轮廓,父轮廓,内嵌轮廓的索引,如果没有对应项,则相应的hierarchy[i]设置为负数。 
//mode轮廓检索模式,可以通过cv::RetrievalModes()查看详细信息

(4)drawContours():

void cv::drawContours   (   InputOutputArray    image,
                            InputArrayOfArrays  contours,
                            int     contourIdx,
                            const Scalar &  color,
                            int     thickness = 1,
                            int     lineType = LINE_8,
                            InputArray  hierarchy = noArray(),
                            int     maxLevel = INT_MAX,
                            Point   offset = Point() 
                        )
//image:输入输出图像,Mat类型即可 
//contours:使用findContours检测到的轮廓数据,每个轮廓以点向量的形式存储,point类型的vector 
//contourIdx:绘制轮廓的只是变量,如果为负值则绘制所有输入轮廓 
//color:轮廓颜色 
//thickness:绘制轮廓所用线条粗细度,如果值为负值,则在轮廓内部绘制 
//lineTpye:线条类型,有默认值LINE_8

运行后得到原图、灰度图、二值化图、轮廓图分别如下

原图

python opencv imread函数 python opencv findcontours_灰度图

灰度图

python opencv imread函数 python opencv findcontours_颜色空间_02

二值化

python opencv imread函数 python opencv findcontours_颜色空间_03

轮廓图

python opencv imread函数 python opencv findcontours_灰度图_04