矢量夹角法分割凹点(需转为python)

矢量夹角法分割凹点(需转为python)

/
opencv4.1.0


#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;

void distance_star(Mat& imge, Mat& outimge) //距离变换函数
void connected_components_stat(Mat& image);   //带统计信息
RNG rng(123);

void distance_star(Mat& imge, Mat& outimge) //距离变换函数
{
	Mat gray, binary;
	//滤波后的二值化
	
	//imshow("binary", binary);

	// distance transform 距离变换
	Mat dist;
	distanceTransform(imge, dist, DistanceTypes::DIST_L2, 3, CV_32F);
	normalize(dist, dist, 0, 1, NORM_MINMAX);  // 归一化函数
	imshow("距离变换图", dist);

	// binary二值化函数
	threshold(dist, outimge, 0.17, 255, THRESH_BINARY);
	imshow("距离变换结果图", outimge);
	waitKey(1000);
	return;

}



void connected_components_stat(Mat& image) {


	int sum = 0;//记录总面积
	int average = 0;//记录平均面积的1/2
	int A = 0;//豌豆数量
	int B = 0;//绿豆数量
	// 二值化
	Mat gray, binary;
	cvtColor(image, gray, COLOR_BGR2GRAY);
	threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
	distance_star(binary, binary);
	Mat dist_m;
	binary.convertTo(binary, CV_8UC1);//通道转换

	//开运算、闭运算
	Mat k = getStructuringElement(MORPH_RECT, Size(13, 13), Point(-1, -1));
	morphologyEx(binary, binary, MORPH_OPEN, k);
	//morphologyEx(binary, binary, MORPH_CLOSE, k);
	 // 形态学操作 - 彩色图像,目的是去掉干扰,让结果更好
	Mat o = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
	morphologyEx(binary, binary, MORPH_ERODE, o);// 腐蚀,去粘连部位的干扰


	//计算连通域
	Mat labels = Mat::zeros(image.size(), CV_32S);
	Mat stats, centroids;
	int num_labels = connectedComponentsWithStats(binary, labels, stats, centroids, 8, 4);//对比新旧函数,用于过滤原始图像中轮廓分析后较小的区域,留下较大区域。

	//使用不同的颜色标记连通域
	vector<Vec3b> colors(num_labels);
	vector<Vec3b> colors1(num_labels);
	// background color
	colors[0] = Vec3b(0, 0, 0);
	colors1[0] = Vec3b(0, 0, 0);
	// object color
	for (int i = 1; i < num_labels; i++) {
		colors1[i] = Vec3b(rng.uniform(125, 125), rng.uniform(125, 125), rng.uniform(125, 125));
		colors[i] = Vec3b(rng.uniform(255, 255), rng.uniform(255, 255), rng.uniform(255, 255));
	}
	//Mat dst = Mat::zeros(image.size(), image.type());

	// render result
	Mat dst = Mat::zeros(image.size(), image.type());
	int w = image.cols;
	int h = image.rows;
	for (int row = 0; row < h; row++) {
		for (int col = 0; col < w; col++) {
			int label = labels.at<int>(row, col);
			if (label == 0) continue;
			dst.at<Vec3b>(row, col) = colors[label];
		}
	}

	//利用统计信息标记连通域
	for (int i = 1; i < num_labels; i++) {
		Vec2d pt = centroids.at<Vec2d>(i, 0);
		int x = stats.at<int>(i, CC_STAT_LEFT);
		int y = stats.at<int>(i, CC_STAT_TOP);
		int width = stats.at<int>(i, CC_STAT_WIDTH);
		int height = stats.at<int>(i, CC_STAT_HEIGHT);
		int area = stats.at<int>(i, CC_STAT_AREA);
		sum += area;
		//printf("area : %d, center point(%.2f, %.2f)\n", area, pt[0], pt[1]);
		//circle(dst, Point(pt[0], pt[1]), 2, Scalar(0, 0, 255), -1, 8, 0);
		//rectangle(dst, Rect(x, y, width, height), Scalar(255, 0, 255), 1, 8, 0);
	}
	average = sum / num_labels;
	for (int i = 1; i < num_labels; i++)
	{
		Vec2d pt = centroids.at<Vec2d>(i, 0);
		int x = stats.at<int>(i, CC_STAT_LEFT);
		int y = stats.at<int>(i, CC_STAT_TOP);
		int width = stats.at<int>(i, CC_STAT_WIDTH);
		int height = stats.at<int>(i, CC_STAT_HEIGHT);
		int area = stats.at<int>(i, CC_STAT_AREA);
		if (area > average) {
			A = A + 1;
			
			circle(dst, CvPoint2D32f(pt[0], pt[1]), 2, Scalar(0, 0, 255), -1, 8, 0);
			//rectangle(dst, Rect(x, y, width, height), Scalar(255, 0, 255), 1, 8, 0);
		}
		else
		{
			B = B + 1;
			circle(dst, CvPoint2D32f(pt[0], pt[1]), 2, Scalar(255, 0, 0), -1, 8, 0);
			//rectangle(dst, Rect(x, y, width, height), Scalar(255, 255, 0), 1, 8, 0);


		}
	}
	//CString str;
	
	printf("豌豆 : %d, \n绿豆:%d", A, B);
	//imwrite("D://3.bmp", dst);
	imshow("二分类图像", dst);
	waitKey(0);
	//nihe(dst);椭圆拟合函数
}


void pro(Mat& img1) //处理图像,所有处理过程均通过这个函数调用处理
{

	IplImage* src= cvLoadImage("D://2.bmp", 0);//原彩色图像的二值化图像,用于转化通道处理

	Mat img = imread("D://2.bmp");


	IplImage* dst = cvCreateImage(cvSize(src->width, src->height), 8, 3);
	CvMemStorage* stor = cvCreateMemStorage(0);
	CvSeq* cont = NULL;
	int num = cvFindContours(src, stor, &cont, sizeof(CvContour), CV_RETR_LIST);      //记录总轮廓数
	int i = 0;
	int j = 0;
	int k = 0;
	float g = 0.0;
	int z = 0;
	float w = 0.0;
	float d = 0.0;
	float flag = 0.0;//没有用到,原本想给个标签的

	float array1[700][3] = { 0.0 };//实际上没有用到这个 这个可以扩展使用




	for (i = 0; cont; cont = cont->h_next)
	{
		int* length = new   int[num];        //作用是记录每个轮廓上的点数
		length[i++] = cont->total;         //记录每个轮廓上的元素个数





		//printf("cont->total:%d\n", cont->total);
		CvPoint* point = new CvPoint[cont->total];
		CvSeqReader reader;
		CvPoint pt = cvPoint(0, 0);
		CvPoint pt1 = cvPoint(0, 0);
		CvPoint pt2 = cvPoint(0, 0);
		CvPoint pt3 = cvPoint(0, 0);
		CvPoint pt4 = cvPoint(0, 0);
		cvStartReadSeq(cont, &reader);
		for (int j = 0; j < cont->total; j++)
		{
			CV_READ_SEQ_ELEM(pt, reader);
			point[j] = pt;
			//cout << pt.x << "  " << pt.y << endl;
		}
		for (j = 0; j < cont->total; j++)
		{
			int k = (j + 1) % cont->total;
			cvLine(dst, point[j], point[k], cvScalar(0, 0, 255), 1, 4, 0);
		}


		for (int j = 0; j < cont->total - 14; j++)
		{
			CV_READ_SEQ_ELEM(pt1, reader);
			CV_READ_SEQ_ELEM(pt2, reader);
			CV_READ_SEQ_ELEM(pt3, reader);
			pt1 = point[j];
			pt2 = point[j + 7];    //取步长为7
			pt3 = point[j + 14];


			if ((pt1.x != pt2.x) & (pt3.x != pt2.x))
			{
				//w = j + 8;
				//int g = int(((pt1.y-pt2.y)/(pt1.x-pt2.x))+ ((pt2.y - pt3.y) / (pt2.x - pt3.x)));
				float g = floor((pt2.x - pt1.x) * (pt3.x - pt2.x) + (pt2.y - pt1.y) * (pt3.y - pt2.y));
				if (g < 1.0)
				{
					//w = j + 8;
					flag = 1;

					//cvLine(dst, point[j], point[j+2], cvScalar(0, 255, 0), 1, 4, 0);
					cvCircle(dst, pt2, 1, Scalar(0, 255, 255), -1);
					array1[z][0] = floor(pt2.x);
					array1[z][1] = floor(pt2.y);
					array1[z][2] = flag;
					z++;

				}
			}
		}

		delete point;
	}


	for (i = 0; i < 700; i++)
	{
		if (array1[i][2] == 1.0)
		{
			for (j = 1; j < 700; j++) {
				w = 35.0;
				float d = sqrt(pow((array1[i][0] - array1[j][0]), 2) +
					pow((array1[i][1] - array1[j][1]), 2));
				if ((d < w) & (d > 5.0)) {
					//w = d;
					CvPoint2D32f pt5 = cvPoint2D32f(0.0, 0.0);
					CvPoint2D32f pt6 = cvPoint2D32f(0.0, 0.0);
					//CvPoint pt6 = cvPoint(0, 0);
					pt5.x = array1[i][0];
					pt5.y = array1[i][1];
					pt6.x = array1[j][0];
					pt6.y = array1[j][1];

					//凹点分割画线
					line(img, pt5, pt6, Scalar(0, 0, 0), 2, 4, 0);
				}
			}
		}
		else {

		}

	}
	cvShowImage("寻找凹点图", dst);

	imshow("凹点分割后", img);
	waitKey(1000);
	connected_components_stat(img);
	return;
}

int main() 
{
	Mat img = imread("D://1.bmp", 0);
	
	进行二值化处理,选择30200.0为阈值
	threshold(img, img, 40, 255, CV_THRESH_BINARY);
	bitwise_not(img, img, Mat());  //对二进制数据进行“非”操作
	imshow("初始灰度图", img);//显示二值化图像
	imwrite("D://2.bmp", img);//保存二值化图像
	waitKey(500);
	pro(img);//处理图像
	return 0;
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值