本文主要是介绍如何根据图片的像素值寻找同一像素值的类,并寻找轮廓圈出图片。
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;
}