高噪点灰度图目标粗定位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;
}
效果: