废料最大利用问题

上周在群里看到一个有趣的外包问题,废料最大化分割利用。用了两个个多小时写的一段分割代码,但是不是最大利用率,不过还行吧!仅供做类似问题的人参考参考!

先来看看问题描述:就是一块不规则的材料,我们要在这个不规则材料上进行切割半径一定圆,使得废料最大化被切割利用,大概应该听懂问题描述了吧,上个图你们就明白问题了。以下是我在模拟处理一块三角形废料的原型和结果。

以上是原图材料,然后在材料上切割指定半径的圆,使得切割的圆最多,这里模拟半径为10个像素,处理后得到以下图像。

二话不说,上代码看看。

bool BORING::detect(cv::Mat &f){

	
	double cr = 10; 		// 定义圆的半径为10个像素
	
	threshDev = 128;		// 二值阈值
	cv::Mat thresh;
	binaryFrame(f, thresh);		// 阈值图像
	// 寻找材料的轮廓
	std::vector<std::vector<cv::Point>> contours;
	cv::findContours(thresh, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
	for (int i = 0; i < contours.size(); i++){
	
		//cv::drawContours(f, contours, i, cv::Scalar(255, 0, 0), 3);
	}
	// 对轮廓求外接矩形
	cv::Rect r0 = cv::boundingRect(contours[0]);
	//cv::rectangle(f, r0, cv::Scalar(255, 0, 0), 1);
	// 取外接矩形减去半径后的新矩形
	cv::Rect r1 = cv::Rect(r0.x + cr,r0.y + cr,r0.width - 2*cr,r0.height - 2*cr);
	//cv::rectangle(f, r1, cv::Scalar(255, 0, 0), 1);
	// 用圆心开始索引
	// 必须让圆心处于材料内并且圆心到材料的最小距离必须大于半径才算可行(可切割)
	bool lineHave = false;
	std::vector<cv::Point> ptv;
	ptv.clear();
	for (int i = 0; i < r1.width; i++){

		for (int j = 0; j < r1.height; j++){

			cv::Point pt = cv::Point(r1.x + i, r1.y + j);
			//It returns positive(inside), negative(outside), or zero(on an edge)
			
			//value, correspondingly.When measureDist = false, the return value is + 1, -1, and 0
			double ret = cv::pointPolygonTest(contours[0], pt, false);
			if (ret == 1.){	// 圆心在材料内部

				ret = cv::pointPolygonTest(contours[0], pt, true);
				if (ret > cr){	// 圆心到材料的最小距离大于半径

					ptv.push_back(pt);
					j += 2*cr;

					lineHave = true;
				}
			}
		}
		if (lineHave){
			lineHave = false;
			i += 2*cr;
		}
	}

	for (int i = 0; i < ptv.size(); i++){

		cv::circle(f, ptv[i], cr, cv::Scalar(255, 0, 0), -1);
	}

	char info[64];
	sprintf(info, "%0.f Pixel Circle", cr);
	cv::putText(f, info, cv::Point(30,30), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 0, 0), 2);
	return true;
}
// 判断点是否在圆内
bool BORING::isPointInCircle(cv::Point pt, cv::Point center, double r){

	if ((((pt.x - center.x) * (pt.x - center.x)) + ((pt.y - center.y) * (pt.y - center.y))) >= (r * r))
		return false;
	return true;
}
// 用于判断两个圆的关系 相交,相接,相离
bool BORING::isFriendTwoCircle(cv::Point center1, double r1, cv::Point center2, double r2){

	if ((((center1.x - center2.x) * (center1.x - center2.x)) + ((center1.y - center2.y) * (center1.y - center2.y)))
		>= ((r1 + r2) * (r1 + r2)))
		return false;
	return true;
}
代码,如上,再来几个材料图像原图和测试结果看看。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值