opencv图片二值化寻找轮廓

本文主要是介绍如何根据图片的像素值寻找同一像素值的类,并寻找轮廓圈出图片。
1.二值化

函数原型double threshold( InputArray src,OutputArray dst,double threshold,double maxval,int type );
参数说明
src:原始数组,可以是Mat类型。
dst:输出数组,必须与 src 的类型一致。
threshold:阈值
maxval:使用 THRESH_BINARY 和 THRESH_BINARY_INV 的最大值。
type:阈值类型
type=THRESH_BINARY:如果 src(x,y)>threshold ,dst(x,y) = max_value; 否则,dst(x,y)=0;
type=THRESH_BINARY_INV:如果 src(x,y)>threshold,dst(x,y) = 0; 否则,dst(x,y) = max_value.
type=THRESH_TRUNC:如果 src(x,y)>threshold,dst(x,y) = max_value; 否则dst(x,y) = src(x,y).
type=THRESH_TOZERO:如果src(x,y)>threshold,dst(x,y) = src(x,y) ; 否则 dst(x,y) = 0。
type=THRESH_TOZERO_INV:如果 src(x,y)>threshold,dst(x,y) = 0 ; 否则dst(x,y) = src(x,y).
原图
在这里插入图片描述
二值化处理

Mat image = imread("C://Users//lenovo//Desktop//test.jpg",1);
	cout <<"Original Image channal:  "<< image.channels() << endl;
	imshow("Original Image", image);
	
	Mat gray;
	cvtColor(image, gray, COLOR_BGR2GRAY);
	imshow("gray Image", gray);
	cout <<"gray Image channal:  "<< gray.channels() << endl;
	// Wait until user press some key
	
	Mat result;
	threshold(gray, result, 170, 255, THRESH_BINARY);
	imshow("threshold Image", result);

在这里插入图片描述
2.查找轮廓
findContours( InputOutputArray image, OutputArrayOfArrays contours,OutputArray hierarchy, int mode, int method, Point offset=Point());

image,单通道图像矩阵,可以是灰度图,但更常用的是二值图像。

contours,定义为“vector<vector> contours”,是一个向量,并且是一个双重向量,向量内每个元素保存了一组由连续的Point(cv定义的数据结构)点构成的点的集合的向量,每一组Point点集就是一个轮廓。 有多少轮廓,向量contours就有多少元素。

hierarchy,定义为“vector hierarchy”, hierarchy向量内每一个元素的4个int型变量——hierarchy[i][0] ~hierarchy[i][3],分别表示第 i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果当前轮廓没有对应的后一个 轮廓、前一个轮廓、父轮廓或内嵌轮廓的话,则hierarchy[i][0] ~hierarchy[i][3]的相应位被设置为默认值-1。

mode,定义轮廓的检索模式。(opencv3请删除CV_,便可使用)CV_RETR_EXTERNAL;CV_RETR_LIST;CV_RETR_CCOMP;CV_RETR_TREE

method,定义轮廓的近似方法
CV_CHAIN_APPROX_NONE;CV_CHAIN_APPROX_SIMPLE;CV_CHAIN_APPROX_TC89_L1

Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值!

3.轮廓绘制
void drawContours//绘制轮廓,用于绘制找到的图像轮廓
(InputOutputArray image,InputArrayOfArrays contours, int contourIdx,const Scalar& color,int thickness = 1, int lineType = 8,InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point())
image,要绘制轮廓的图像,可以创建一个与原图大小一样的空白图。
contours,所有输入的轮廓,每个轮廓被保存成一个point向量。
color,绘制轮廓所用的颜色。
thickness = 1, 绘制轮廓的线的粗细,如果是负数,则轮廓内部被填充。
lineType = 8, 绘制轮廓的线的连通性。
hierarchy = noArray(),关于层级的可选参数,只有绘制部分轮廓时才会用到。
int maxLevel = INT_MAX,//绘制轮廓的最高级别,这个参数只有hierarchy有效的时候才有效
//maxLevel=0,绘制与输入轮廓属于同一等级的所有轮廓即输入轮廓和与其相邻的轮廓 。
//maxLevel=1, 绘制与输入轮廓同一等级的所有轮廓与其子节点。 //maxLevel=2,绘制与输入轮廓同一等级的所有轮廓与其子节点以及子节点的子节点
**offset = Point()**点的偏移量。
4.完整应用

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;
int main()
{
	Mat image = imread("C://Users//lenovo//Desktop//test.jpg",1);
	cout <<"Original Image channal:  "<< image.channels() << endl;
	imshow("Original Image", image);
	
	Mat gray;
	cvtColor(image, gray, COLOR_BGR2GRAY);
	imshow("gray Image", gray);
	cout <<"gray Image channal:  "<< gray.channels() << endl;
	// Wait until user press some key
	
	Mat result;
	threshold(gray, result, 170, 255, THRESH_BINARY);
	imshow("threshold Image", result);

	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;

	findContours(result, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());

	Mat imageContours = Mat::zeros(image.size(), CV_8UC1);
	Mat Contours = Mat::zeros(image.size(), CV_8UC1); //绘制

	for (int i=0;i< contours.size();i++)
	{
		//contours[i]代表的是第i个轮廓,contours[i].size()代表的是第i个轮廓上所有的像素点数
		for (int j = 0; j < contours[i].size(); j++)
		{
			//绘制出contours向量所有的像素点
			Point P = Point(contours[i][j].x, contours[i][j].y);
			Contours.at<uchar>(P) = 255;
			imshow("Contours image", Contours);//点图
		}
		//绘制轮廓
		drawContours(imageContours, contours, i,255, 1, 8, hierarchy);
	}
	imshow("drawContours image", imageContours); //轮廓
	

	waitKey(0);
	return 0;	
}

在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenCV可以使用函数fillPoly来填充二值图像中的孔洞轮廓。fillPoly函数可以填充多边形区域,使用该函数可以将图像中指定的多边形形状内的像素点颜色填充为指定的灰度值或颜色。 使用fillPoly函数填充孔洞轮廓的步骤如下: 1. 首先,需要准备一个与要填充的孔洞轮廓相同大小的图像作为掩膜(mask),该图像的像素值应初始化为0。 2. 然后,需要将孔洞轮廓的顶点坐标按照顺时针或逆时针的顺序保存在一个numpy数组中。 3. 调用fillPoly函数,将掩膜图像、保存顶点坐标的数组、数组长度作为参数传入。 4. 设置要填充的颜色或灰度值。 5. 调用imshow函数显示填充后的图像。 以下是一个示例代码: import numpy as np import cv2 # 创建与原始图像大小一致的掩膜 mask = np.zeros((height, width), dtype=np.uint8) # 定义孔洞轮廓的顶点坐标 contour = np.array([[100, 100], [200, 100], [200, 200], [100, 200]], dtype=np.int32) # 使用fillPoly函数填充孔洞轮廓 cv2.fillPoly(mask, [contour], 255) # 设置填充颜色为白色 color = (255, 255, 255) # 将填充结果显示出来 result = cv2.bitwise_and(image, image, mask=mask) result = cv2.cvtColor(result, cv2.COLOR_BGR2RGB) # 将BGR格式转为RGB格式 cv2.imshow("Filled Image", result) cv2.waitKey(0) cv2.destroyAllWindows() 这样就可以使用OpenCV中的fillPoly函数来实现填充二值图像中的孔洞轮廓。注意,使用fillPoly填充孔洞轮廓前,需要先创建一个与原始图像大小一致的掩膜图像,并将孔洞轮廓的顶点坐标按照顺时针或逆时针的顺序保存在一个numpy数组中。 ### 回答2: 使用OpenCV填充二值图中的孔洞轮廓可以通过以下步骤实现: 1. 首先,加载二值图像并确保图像中只有两个像素值0和255(或1和0),其中0代表背景像素,255(或1)代表对象像素。 2. 使用OpenCV的findContours函数找到图像中对象的轮廓。该函数返回边界点的列表。 3. 遍历每个轮廓,使用OpenCV的drawContours函数将轮廓绘制在一个单独的黑色背景图像上。 4. 将绘制轮廓的黑色图像进行二值化,将轮廓内部的像素设置为255。 5. 在原始的二值图像上使用bitwise_or函数与上述二值化的图像进行逻辑或操作。此操作将使用轮廓来填充孔洞。 以下是示例代码: ```python import cv2 import numpy as np # 加载二值图像 image = cv2.imread('binary_image.png', cv2.IMREAD_GRAYSCALE) # 创建黑色背景图像 filled_image = np.zeros_like(image) # 寻找轮廓 contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 绘制轮廓 cv2.drawContours(filled_image, contours, -1, (255), thickness=cv2.FILLED) # 二值化填充后的图像 filled_image = cv2.threshold(filled_image, 1, 255, cv2.THRESH_BINARY)[1] # 逻辑或操作填充孔洞 filled_image = cv2.bitwise_or(image, filled_image) # 显示填充后的图像 cv2.imshow('Filled Image', filled_image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 上述代码中,我们首先加载二值图像。然后使用findContours函数找到轮廓,并在黑色背景图像上绘制轮廓。接下来,将绘制轮廓的图像进行二值化,然后使用bitwise_or函数与原始二值图像进行逻辑或操作。最后,显示填充后的图像。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值