高噪点灰度图目标粗定位CoraseLocation

高噪点的灰度图目标粗定位

/*
** @name: CoraseLocation
** @brief: 粗定位
** @param:[in] srcGray  灰度图()
** @param:[in] box      目标尺寸(像素)
** @param:[ou] roi      目标定位结果
** @return: true=成功,false=失败
*/
bool CoraseLocation(cv::Mat& srcGray, cv::Size box, cv::Rect& roi){
	try
	{
		if (srcGray.empty()) return false;
		if (srcGray.channels() != 1) return false;
		if (box.width < 4 || box.width >= srcGray.cols) return false;
		if (box.height < 4 || box.height >= srcGray.rows) return false;
		//
		roi = cv::Rect(0, 0, srcGray.cols, srcGray.rows);

		// STEP01: 计算影像平均灰度与标准差
		cv::Scalar meanVal, devVal;
		cv::meanStdDev(srcGray, meanVal, devVal);

		// STEP02: 计算积分图(寻找目标:亮区或暗区)
		cv::Mat srcInte;
		cv::integral(srcGray, srcInte, CV_64F);

		// STEP03: 寻找亮区和暗区
		cv::Point ptMin(-1, -1), ptMax(-1, -1);
		double    valMin = DBL_MAX, valMax = DBL_MIN;
		for (int y = 0; y < srcInte.rows - box.height; y += box.height / 2){
			for (int x = 0; x < srcInte.cols - box.width; x += box.width / 2){
				double left_top = srcInte.at<double>(y, x);
				double left_bottom = srcInte.at<double>(y + box.height, x);
				double right_top = srcInte.at<double>(y, x + box.width);
				double right_bottom = srcInte.at<double>(y + box.height, x + box.width);
				//
				double valBox = right_bottom - left_bottom - right_top + left_top;
				if (valMin > valBox){
					valMin = valBox;
					ptMin.x = x + 1;
					ptMin.y = y + 1;
				}
				if (valMax < valBox){
					valMax = valBox;
					ptMax.x = x + 1;
					ptMax.y = y + 1;
				}
			}
		}
		valMin /= box.area();
		valMax /= box.area();

		// STEP04: 判断目标是亮区还是暗区,并重新转换为二值图
		bool isWhiteMark = false;
		cv::Mat srcBin;
		if (abs(valMin - meanVal[0]) > abs(valMax - meanVal[0])){
			// valmin: mark为暗
			roi = cv::Rect(ptMin.x, ptMin.y, box.width, box.height);
			isWhiteMark = false;
			cv::threshold(srcGray, srcBin, valMin - devVal[0], 255, cv::THRESH_BINARY_INV);
		}
		else {
			// valmax: mark为亮
			roi = cv::Rect(ptMax.x, ptMax.y, box.width, box.height);
			isWhiteMark = true;
			cv::threshold(srcGray, srcBin, valMax + devVal[0], 255, cv::THRESH_BINARY);
		}

		// STEP05: 根据二值图,调整目标区域
		std::vector<std::vector<cv::Point>> contours;
		cv::findContours(srcBin, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
		valMax = DBL_MIN;
		int idxMax = -1;
		for (int i = 0; i < contours.size(); ++i){
			auto area = cv::contourArea(contours[i]);
			if (valMax < area){
				valMax = area;
				idxMax = i;
			}
		}
		if (idxMax < 0){
			return -1;
		}

		// STEP06: 输出拟合后的目标区域
		roi = cv::boundingRect(contours[idxMax]);
		return true;
	}
	catch (...)
	{
		
	}
	return false;
}

效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值