opencv c++常用代码(二)

#include <iostream>
#include <opencv2/opencv.hpp>
#include <numeric>
#include <cmath>
#

using namespace cv;
using namespace std;

//remove Light difference by using top hat
Mat moveLightDiff(Mat src, int radius)
{
    
    
	Mat dst;
	Mat srcclone = src.clone();
	Mat mask = Mat::zeros(radius * 2, radius * 2, CV_8U);
	circle(mask, Point(radius, radius), radius, Scalar(255), -1);
	//top hat
	dilate(srcclone, srcclone, mask);
	erode(srcclone, srcclone, mask);
	
	dst = srcclone - src;

	
	return dst;




}


Mat RegionGrow(Mat src, Point2i pt, int th)
{
    
    
	Point2i ptGrowing;						//待生长点位置
	int nGrowLable = 0;								//标记是否生长过
	int nSrcValue = 0;								//生长起点灰度值
	int nCurValue = 0;								//当前生长点灰度值
	int num = 0;
	bool flag = true;
	Mat matDst = Mat::zeros(src.size(), CV_8UC1);	//创建一个空白区域,填充为黑色
	Mat temp = Mat::zeros(src.size(), CV_8UC1);	//创建一个空白区域,填充为黑色
													//生长方向顺序数据
	int DIR[8][2] = {
    
     {
    
     -1, -1 },{
    
     0, -1 },{
    
     1, -1 },{
    
     1, 0 },{
    
     1, 1 },{
    
     0, 1 },{
    
     -1, 1 },{
    
     -1, 0 } };
	vector<Point2i> vcGrowPt;						//生长点栈
	vcGrowPt.push_back(pt);							//将生长点压入栈中
	matDst.at<uchar>(pt.y, pt.x) = 255;				//标记生长点
	nSrcValue = src.at<uchar>(pt.y, pt.x);			//记录生长点的灰度值

	while (!vcGrowPt.empty() && flag)						//生长栈不为空则生长
	{
    
    
		pt = vcGrowPt.back();						//取出一个生长点
		vcGrowPt.pop_back();

		//分别对八个方向上的点进行生长
		for (int i = 0; i<9; ++i)
		{
    
    
			ptGrowing.x = pt.x + DIR[i][0];
			ptGrowing.y = pt.y + DIR[i][1];
			//检查是否是边缘点
			if (ptGrowing.x < 0 || ptGrowing.y < 0 || ptGrowing.x >(src.cols - 1) || (ptGrowing.y > src.rows - 1))
				continue;

			nGrowLable = matDst.at<uchar>(ptGrowing.y, ptGrowing.x);		//当前待生长点的灰度值

			if (nGrowLable == 0)					//如果标记点还没有被生长
			{
    
    
				nCurValue = src.at<uchar>(ptGrowing.y, ptGrowing.x);
				if (abs(nSrcValue - nCurValue) < th)					//在阈值范围内则生长
				{
    
    
					matDst.at<uchar>(ptGrowing.y, ptGrowing.x) = 255;		//标记为白色
					vcGrowPt.push_back(ptGrowing);					//将下一个生长点压入栈中
					num++;
					if (num > 500)
					{
    
    
						
						flag = false;
						break;
					}
				}
			}
		}
	}
	cout << num << endl;
	if (num > 300)
	{
    
    
		return temp.clone();
	}
	else
	{
    
    
		return matDst.clone();
	}
	
}


int main()
{
    
    
	Mat src = imread("1-1.jpg");
	Mat src_hsv;
	cvtColor(src, src_hsv, COLOR_BGR2HSV);
	Mat src_h, src_binary;
	Mat src_gray;

	cvtColor(src, src_gray, COLOR_BGR2GRAY);
	int height, width;
	height = src_gray.rows;
	width = src_gray.cols;

	vector<Mat> rgb_planes;
	split(src_hsv, rgb_planes);
	src_h = rgb_planes[0]; // h channel is useful

	int r = (height < width ? height : width)/ 2 ;

	

	// 开运算
	Mat src_open, src_guass;
	Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(13, 13), Point(-1, -1));
	// Mat src_open;
	morphologyEx(src_gray, src_open, CV_MOP_OPEN, kernel);

	//高斯滤波
	GaussianBlur(src_open, src_guass, Size(5, 5), 3);

	morphologyEx(src_guass, src_h, CV_MOP_BLACKHAT, kernel);

	/*int radius  = 3;
	Mat mask = Mat::zeros(radius * 2, radius * 2, CV_8U);
	circle(mask, Point(radius, radius), radius, Scalar(255), -1);
	
	erode(src_gray, src_gray, mask);
	dilate(src_gray, src_open, mask);*/
	namedWindow("src_open", WINDOW_NORMAL);
	imshow("src_open", src_open);


	//imwrite("img_open3.jpg", src_open);
	// top hat
	//src_h = moveLightDiff(src_open, 5);

	namedWindow("src_h", WINDOW_NORMAL);
	imshow("src_h", src_h);

	// 直方图统计

	float hist[256] = {
    
    0};

	for (int i = 0; i < src_gray.rows; i++)
	{
    
    
		for (int j = 0; j < src_gray.cols; j++)
		{
    
    
			
			int val = src_gray.at<uchar>(i, j);
			if (val > 0)
			{
    
    
				hist[val]++;
			}
			
		}
	}
	/*for (int i = 0; i < 256; i++)
	{
		cout << hist[i] << endl;
	}
	*/
	Mat imgn = Mat::zeros(height, width, CV_32FC1);
	int w = 3;
	for (int i = w; i < height - w; i++)
	{
    
    
		//float* uc_pixel = imgn.data + i*imgn.step;
		for (int j = w; j < width - w; j++)
		{
    
    
			float histm[256] = {
    
     0 };
			for (int p = i - w; p < i+ w +1; p++)
			{
    
    
				for (int q = j - w; q < j + w+1; q++)
				{
    
    
					int val = src_h.at<uchar>(p, q);
					histm[val]++;
				}

			}
			float hist_prob[256] = {
    
     0 };
			/*int hist_sum = 0;*/
			/*for (int s = 0; s < 256; s++)
			{
				cout << histm[s] << endl;

			}
			cout <<"...." << endl;*/


			float hist_sum = accumulate(histm, histm + 256, 0);

			//cout << hist_sum << endl;
			for (int k = 0; k < 256; k++)
			{
    
    
				hist_prob[k] = float(histm[k]) / float(hist_sum);
				//cout << hist_prob[k] << endl;

			}
			double entropy = 0;
			for (int  kk = 0; kk < 256; kk++)
			{
    
    
				if (hist_prob[kk] != 0)
				{
    
    
					entropy = entropy + hist_prob[kk] * log(1 / hist_prob[kk]);
				}

			}
			//uc_pixel[j] = entropy;
			// cout << entropy << endl;
			imgn.at<float>(i, j) = entropy;
		}

	}

	double minv, maxv;
	Point pt_min, pt_max;
	minMaxLoc(imgn, &minv, &maxv, &pt_min, &pt_max);

	Mat imgn1 = Mat::zeros(height, width, CV_8UC1);;
	for (int i = 0; i < imgn.rows; i++)
	{
    
    
		for (int j = 0; j < imgn.cols; j++)
		{
    
    
			float value = imgn.at<float>(i, j);
			imgn1.at<uchar>(i, j) = round(255 * double(value - minv) / double(maxv - minv));

		}

	}


	//imgn.convertTo(imgn, CV_8UC1);
	namedWindow("src_en", WINDOW_NORMAL);
	imshow("src_en", imgn1);

	threshold(imgn1, src_binary, 150, 255, THRESH_BINARY );
	namedWindow("src_binary", WINDOW_NORMAL);
	imshow("src_binary", src_binary);

	vector<vector<Point>> bin_contours;

	vector<Vec4i> bin_hireachy;

	

	findContours(src_binary, bin_contours, bin_hireachy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point());

	//计算轮廓矩
	vector<Point2f> mc;
	for (int i = 0; i < bin_contours.size(); i++)
	{
    
    
		double area1 = contourArea(bin_contours[i]);
		if (area1 > 4)
		{
    
    
			RotatedRect rect = minAreaRect(bin_contours[i]);
			double x0, y0;
			x0 = rect.center.x;                    //  中心位置
			y0 = rect.center.y;
			mc.push_back(rect.center);
			//mu.push_back( moments(bin_contours[i], false));
		}
		
		
	}

	计算轮廓的质心
	//vector<Point2f> mc(mu.size());
	for (int i = 0; i < mc.size(); i++)
	{
    
    
		//mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
		cout << mc[i].x <<"   " << mc[i].y<< endl;
	}


	// 区域生长
	int th = 40;
	Mat dst;
	Mat res = Mat::zeros(src_gray.size(), CV_8UC1);
	for (int i = 0; i < mc.size(); i++)
	{
    
    
		Point2f pt = mc[i];
		dst = RegionGrow(src_gray, pt, th);
		bitwise_or(res, dst, res);
		

	}


	namedWindow("src_res", WINDOW_NORMAL);
	imshow("src_res", res);

	//for (int i = 0; i < src_binary.rows; i++)
	//{
    
    
	//	for (int  j = 0; j < src_binary.cols; j++)
	//	{
    
    
	//		int tmp = src_binary.at<uchar>(i, j);
	//		if (tmp != 0)
	//		{
    
    

	//		}

	//	}

	//}


	/*int blockSize = 31;
	int constValue = 7;
	cv::Mat local;
	cv::adaptiveThreshold(src_open, local, 255, ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, blockSize, constValue);

	namedWindow("src_local", WINDOW_NORMAL);
	imshow("src_local", local);*/

	//threshold(src_h, src_binary, 0, 255, THRESH_BINARY | THRESH_OTSU);

	//Mat imgn_dst;
	//bitwise_and(local, src_binary, imgn_dst);

	//namedWindow("src_bit", WINDOW_NORMAL);
	//imshow("src_bit", imgn_dst);



	


	
	//imshow("src_open", src_open);

	vector<vector<Point>> contours;

	vector<Vec4i> hireachy;

	//Moments monents;
	
	findContours(res, contours, hireachy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point());

	//for (int i = 0; i < contours.size(); i++)
	//{
    
    
	//	//Scalar color(rand() & 255, rand() & 255, rand() & 255);
	//	cv::drawContours(src, contours, i, Scalar(0, 255, 0), 1, 8);
	//}

	//vector<vector<Point>> contours_poly(contours.size());
	vector<Point2f>center(contours.size());   //包围点集的最小圆形vector
	vector<float>radius(contours.size());
	for (int i = 0; i < contours.size(); i++)
	{
    
    
		//approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);

		minEnclosingCircle(contours[i], center[i], radius[i]); //

	}
	for (int i = 0; i < contours.size(); i++)
	{
    
    
		//Scalar color(rand() & 255, rand() & 255, rand() & 255);
		//cv::drawContours(src, contours, i, Scalar(0, 255, 0), 1, 8);
		circle(src, center[i], (int)radius[i], Scalar(0, 0, 255), 1, 8, 0);
		cout << radius[i] << endl;
		char  diameter[20];
		sprintf_s(diameter, "%d", 2 * (int)radius[i]);
		cv::Point origin;
		origin.x = center[i].x + 3;
		origin.y = center[i].y - 3;
		putText(src, diameter, origin, CV_FONT_HERSHEY_SCRIPT_SIMPLEX, 0.55, Scalar(0, 255, 0));
	}



	namedWindow("src_contours", WINDOW_NORMAL);
	imshow("src_contours", src);


	Mat result = Mat::zeros(src.size(), CV_8UC3);

	waitKey(0);
	system("pause");
	return 0;
}


#include <iostream>
#include <opencv2\opencv.hpp>
#include <cmath>
#include<algorithm>

using namespace std;
using namespace cv;



//Mat & image_segmentation(Mat& img, int cluster_n, int m, int cnt, double erro)
//{
    
    
//	int m = img.rows;
//	int n = img.cols;
//
//
//
//}

//double cal_distance(Point2f center, vector<double> data)
//{
    
    
//
//}
void initfcm(int cluster_n, int data_n, cv::OutputArray U)
{
    
    
	Mat U_temp(cluster_n, data_n, CV_32F);
	randu(U_temp, Scalar::all(0), Scalar::all(1));//Scalar:;all是4空间内容全为N,可以用来当作常数使用
												  //randu(U_temp, Scalar(0), Scalar(1)); 通过这里可以发现问题:应学会查阅官方文档,randu的上下限是Vector或者Mat结构,randu产生随机矩阵,用于初始化
	Mat U1, U2;
	//U1 = U_temp(Range(0, 1), Range::all()).clone();// Range::all() 全部 // 提取第0行,不包括第1行
	//U2 = U_temp(Range(1, 2), Range::all()).clone();
	//U1 = U1 + U2;
	U1 = Mat::zeros(1, data_n, CV_32FC1);
	reduce(U_temp, U1, 0, CV_REDUCE_SUM); //相当于matlab sum
	repeat(U1, cluster_n, 1, U2);
	//Mat U3;
	//repeat(U1, 2, 1, U3);//垂直方向复制1次,水平方向复制0次,注意是i+1 与i+0,返回复制扩容后的U3
	U_temp = U_temp.mul(1 / U2);
	U_temp.copyTo(U);//返回mat类形参

}

//子函数2:聚类过程,返回更新后的聚类中心 隶属度矩阵U 目标函数,注意这里的目标函数是一个数,需在主函数里填充到矩阵中

void stepfcm(cv::InputArray data, cv::InputArray U, int cluster_n, int expo, double *obj_fcn_one, cv::OutputArray center, cv::OutputArray U_new)
{
    
    
	Mat temp, temp1;
	
	Mat A = Mat::ones(U.getMat().rows, U.getMat().cols, CV_32FC1);

	Mat temp2;
	absdiff(A, U, temp2);
	
	float alpha = 0.85;
	int pp = U.getMat().cols;
	Mat temp3;
	pow(U.getMat(),  alpha, temp3);
	absdiff(A, temp3, temp3);
	//convertScale(temp3, temp3, 1 / alpha);
	temp3 = temp3.mul(1 / alpha);
	
	Mat Ut;
	absdiff(temp2, temp3, Ut);


	Mat temp4;
	
	reduce(Ut, temp4, 1, CV_REDUCE_SUM);

	Mat pai = temp4.mul(1 / pp);
	Mat obj;
	Mat temp5;
	
	temp5 = 1 - pai;
	exp(temp5, temp5);
	obj = pai.mul(temp5);
	
	Scalar objs = sum(obj);

	Mat Ud;
	add(U.getMat(), Ut, Ud);
	Mat nf, mf;
	pow(U.getMat(), expo, mf); // C++中矩阵每一个元素求阶乘
	Ud.copyTo(nf);
	Mat data_trans;
	transpose(data.getMat(), data_trans);
	reduce(mf, temp, 1, CV_REDUCE_SUM);//矩阵行列求和的操作,转化成了2*1的列向量 dim=0,单行,dim=1,单列,CE_SUM 行列之和,AVG:行列向量的均值向量,MAX,MIN输出行列的最大最小值
	// transpose(mf, mf);
	Mat d = Mat::zeros(U.getMat().rows, U.getMat().cols, CV_32FC1);
	
	for (int i = 0; i < d.rows; i++)
	{
    
    
		data_trans.copyTo(d.row(i));

	}

	


	Mat divisor = mf.mul(d);
	reduce(divisor, temp1, 1, CV_REDUCE_SUM);

	// reduce(divisor, temp1, 1, CV_REDUCE_SUM);
	/*transpose(temp, temp);
	Mat res = (Mat::ones(data.getMat().cols, 1, CV_32F)) * temp;
	transpose(res, res);*/
	Mat result = temp1.mul(1/temp);
	result.copyTo(center);


	//计算样本点距离聚类中心的距离
	//out = zeros(size(center, 1), size(data, 1));
	Mat dist = Mat::zeros(result.rows, data.getMat().rows, CV_32F);
	for (int k = 0; k < result.rows; k++)
	{
    
    
		Mat a = Mat::ones(data.getMat().rows, 1, CV_32F) * result(Range(k, k + 1), Range::all());
		Mat b = data.getMat();
		Mat c;
		b.convertTo(c, CV_32F, 1, 0);

		Mat temp; // abs(data.getMat() - Mat::ones(data.getMat().rows, 1, CV_32F) * result(Range(k, k + 1), Range::all()));
		absdiff(a, c, temp);
		transpose(temp, temp);
		//dist(Range(k, k + 1), Range::all()) = temp;//dist(Range(k, k + 1), Range::all()) = temp;这样的矩阵赋值方式是无效的。
		dist(Range(k, k + 1), Range::all()) = dist(Range(k, k + 1), Range::all()) + temp;
	}
	// 计算目标函数
	//obj_fcn = sum(sum((dist. ^ 2).*mf));
	*obj_fcn_one = sum(dist.mul(dist).mul(mf))[0] + objs[0];  //sum返回的是Scalar类,是一个4空间向量
													// 计算距离聚类中心的距离
	Mat tmp;
	pow(dist, (-2 / (expo - 1)), tmp); //void pow(InputArray src, double power, OutputArray dst);
	Mat Tmp;
	reduce(tmp, Tmp, 0, CV_REDUCE_SUM);
	// 新的隶属度矩阵
	Mat Unew = tmp.mul(1 / ((Mat::ones(cluster_n, 1, CV_32F)) * Tmp));
	Unew.copyTo(U_new);
}
void ClustFCM(cv::InputArray image, cv::OutputArray U, cv::OutputArray obj_fcn, cv::OutputArray center, int cluster_n, float * option)
{
    
    //输出:
 //center----聚类中心 2x1的矩阵
 //U----隶属度矩阵 矩阵
 //obj_fcn----目标函数值矩阵
	
	Mat data = image.getMat();
	double data_n = data.rows;//样本数
	int in_n = data.cols;//特征维度
	int expo = option[0];      //隶属度矩阵U的指数
	int max_iter = option[1]; // 最大迭代次数
	float min_impro = option[2]; // 隶属度最小变化量, 迭代终止条件
	int display = option[3]; // 每次迭代是否输出信息标志
	initfcm(cluster_n, data_n, U); //输出U,初始化隶属度矩阵(子函数1)
	cv::Mat U_new;

	Mat obj_fcn_begin = Mat::zeros(max_iter, 1, CV_32F);//初始化目标函数矩阵

	double obj_fcn_ones;// 此处是一个数,用来填充目标函数初始化矩阵
	int iter_n; //实际迭代次数
	for (int i = 1; i <= max_iter; i++)
	{
    
    
		//[U, center, obj_fcn(i)] = stepfcm(data, U, cluster_n, expo);
		//在第k步循环中改变聚类中心ceneter,和分配函数U的隶属度值;
		stepfcm(data, U, cluster_n, expo, &obj_fcn_ones, center, U);  //聚类过程:返回修改后的目标函数、聚类中心,隶属度矩阵(子函数2)
		obj_fcn_begin.at<float>(i - 1, 0) = obj_fcn_ones; //填充目标函数初始化矩阵
		if (display == 1)
		{
    
    
			cout << "第 迭代次数:" << i << "目标函数值:" << obj_fcn_ones << endl;
		}
		
		//U = U_new;
		if (i > 1)
		{
    
    
			if (abs(obj_fcn_begin.at<float>(i - 1, 0) - obj_fcn_begin.at<float>(i - 2, 0))< min_impro)
			{
    
    
				iter_n = i;
				break;
			}
		}
	}
	Mat obj_fcn_end = obj_fcn_begin(Range(0, iter_n), Range::all()); //根据迭代次数,丢弃目标函数矩阵多余0位
	obj_fcn_end.copyTo(obj_fcn); // 返回Mat类形参数据
}

//子函数1:初始化函数,返回初始化隶属度矩阵



//void pow(InputArray src, double power, OutputArray dst)
//{
    
    
//	dst = src
//
//}

void image_segmentation(cv::Mat img, int cluster_n, float * option, cv::Mat &result)
{
    
    

	int m = img.rows;
	int n = img.cols;
	int num = m * n;
	Mat imgn = img.reshape(0, num); //通道数不变,
	cv::InputArray ptr = imgn;

	cv::Mat U;//U.create(Size(cluster_n, m *n),img.type());
	cv::Mat	obj_fcn;

	cv::Mat  center;

	ClustFCM(ptr, U, obj_fcn, center, cluster_n, option);
	Mat maxU;
	reduce(U, maxU, 0, CV_REDUCE_MAX);  //找出每一列的最大隶属度

	Mat_<double>  temp;
	//sort(center, temp, CV_SORT_EVERY_COLUMN + CV_SORT_ASCENDING); //排序输出序号

	//center排序
	Mat center_sort;

	center.copyTo(center_sort);

	for (int i = 0; i < center.rows; i++)
	{
    
    
		for (int j = i + 1; j < center.rows; j++)
		{
    
    
			if (center_sort.at<float>(i, 0) > center_sort.at<float>(j, 0))
			{
    
    
				float tmp = center_sort.at<float>(i, 0);
				center_sort.at<float>(i, 0) = center_sort.at<float>(j, 0);
				center_sort.at<float>(j, 0) = tmp;
			}

		}

	}
	//Mat result;
	//imgn.copyTo(result);
	//result = img.reshape(0, 1);
	result = Mat::zeros(1, num, CV_32F);

	float* data = result.ptr<float>(0);

	int grays = 0;
	// vector<vector<int>> class_num;
	for (int i = 0; i < cluster_n; i++)
	{
    
    
		Mat cla = U.row(i);
		//vector<int> index;

		//class_num.push_back(index);


		int id = 0;
		for (int k = 0; k < center.rows; k++)
		{
    
    
			if (center_sort.at<float>(k, 0) == center.at<float>(i, 0))
			{
    
    
				id = k;
				break;
			}
		}


		if (id == 0)
		{
    
    
			grays = 0;

		}
		else if (id == cluster_n - 1)
		{
    
    
			grays = 255;
		}
		else
		{
    
    
			grays = floor(255 * id / (cluster_n - 1));
		}

		/*for (int l = 0; l < index.size(); l++)
		{
		data[index[l]] = grays;
		}

		index.clear();*/
		//index.shrink_to_fit();

		for (int j = 0; j < cla.cols; j++)
		{
    
    
			float x = U.at<float>(i, j);
			float y = maxU.at<float>(0, j);
			if (x == y)
			{
    
    
				data[j] = grays;
				// index.push_back(j);
			}
		}

	}

	result = result.reshape(0, m);

}



int main()
{
    
    

	Mat src = imread("24.jpg");
	Mat img;
	cvtColor(src, img, CV_BGR2GRAY);
	int thresh_1 = 0.5;
	int thresh_2 = 0.1;
	// 
	int height = img.rows;
	int width = img.cols;
	int k_size = max(height, width);
	Mat kernel = getStructuringElement(MORPH_RECT, Size(k_size, k_size));
	morphologyEx(img, img, MORPH_TOPHAT, kernel); 
	namedWindow("2", 0);
	imshow("2", img);
	//int m = img.rows;
	//int n = img.cols;
	//int num = m * n;
	//Mat imgn = img.reshape(0, num); //通道数不变,
	//cv::InputArray ptr = imgn;//(uchar **)malloc(m * sizeof(uchar *));//二维数组ptr[][]

	int cluster_n = 4;
	
	float option[4] = {
    
     2, 500, 1e-5, 1 };
	Mat result;
	image_segmentation(img, cluster_n, option, result);

	//result.convertTo(result, CV_8UC1, 1, 0);
	namedWindow("3", 0);
	imshow("3", result);

	Mat bin_img;
	//int thresh = 10;
	threshold(result, bin_img, 128, 255, THRESH_BINARY);
	cv::namedWindow("binary_img", 0);
	cv::imshow("binary_img", bin_img);
	imwrite("bin.jpg", bin_img);

	Mat bi_img;
	bin_img.convertTo(bi_img, CV_8U);
	

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	findContours(bi_img, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point());
	std::vector<cv::RotatedRect> box(contours.size()); //最小外接矩形
	vector<Rect> boundRect(contours.size());  //定义外接矩形集合
	cv::Point2f rect[4];
	float center_x, center_y;
	std::vector<cv::Point2f> pts_src;
	int maxW = 0;
	int maxH = 0;
	for (int i = 0; i < contours.size(); i++)
	{
    
    
		//绘制轮廓  
		cv::drawContours(src, contours, i, cv::Scalar(255, 0, 0), 1, 8, hierarchy);

		box[i] = minAreaRect(Mat(contours[i]));  //计算每个轮廓最小外接矩形
	    boundRect[i] = boundingRect(Mat(contours[i]));
		if (boundRect[i].width > maxW)
		{
    
    
			maxW = boundRect[i].width;
		}

		if (boundRect[i].height > maxH)
		{
    
    
			maxH = boundRect[i].height;
		}
		//box[i].points(rect);  //把最小外接矩形四个端点复制给rect数组
		rectangle(src, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(0, 255, 0), 2, 8);




	}

	cv::namedWindow("contour_img", 0);
	cv::imshow("contour_img", src);


	Mat bin;
	convertScaleAbs(bin_img, bin, 1.0 / 255);


	double area = sum(bin)[0];

	cout << area << endl;
	float rate = area / (height * width);
	
	if (rate > thresh_1)
	{
    
    
		cout << "不合格品" << endl;
	}
	if ((abs(maxW - width) < 5 || abs(maxH - height) < 5) && rate > thresh_2)
	{
    
    
		cout << "不合格品" << endl;
	}
	

	waitKey(0);

	system("pause");

	return 0;
}

猜你喜欢

转载自blog.csdn.net/shuaijieer/article/details/125584584