您可以使用HSV色彩空间来提取色调信息。
下面是一些代码有意见,如果有任何问题随时问:
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/StackOverflow/Input/coloredLines.png");
// convert to HSV color space
cv::Mat hsvImage;
cv::cvtColor(input, hsvImage, CV_BGR2HSV);
// split the channels
std::vector<cv::Mat> hsvChannels;
cv::split(hsvImage, hsvChannels);
// hue channels tells you the color tone, if saturation and value aren't too low.
// red color is a special case, because the hue space is circular and red is exactly at the beginning/end of the circle.
// in literature, hue space goes from 0 to 360 degrees, but OpenCV rescales the range to 0 up to 180, because 360 does not fit in a single byte. Alternatively there is another mode where 0..360 is rescaled to 0..255 but this isn't as common.
int hueValue = 0; // red color
int hueRange = 15; // how much difference from the desired color we want to include to the result If you increase this value, for example a red color would detect some orange values, too.
int minSaturation = 50; // I'm not sure which value is good here...
int minValue = 50; // not sure whether 50 is a good min value here...
cv::Mat hueImage = hsvChannels[0]; // [hue, saturation, value]
// is the color within the lower hue range?
cv::Mat hueMask;
cv::inRange(hueImage, hueValue - hueRange, hueValue + hueRange, hueMask);
// if the desired color is near the border of the hue space, check the other side too:
// TODO: this won't work if "hueValue + hueRange > 180" - maybe use two different if-cases instead... with int lowerHueValue = hueValue - 180
if (hueValue - hueRange < 0 || hueValue + hueRange > 180)
{
cv::Mat hueMaskUpper;
int upperHueValue = hueValue + 180; // in reality this would be + 360 instead
cv::inRange(hueImage, upperHueValue - hueRange, upperHueValue + hueRange, hueMaskUpper);
// add this mask to the other one
hueMask = hueMask | hueMaskUpper;
}
// now we have to filter out all the pixels where saturation and value do not fit the limits:
cv::Mat saturationMask = hsvChannels[1] > minSaturation;
cv::Mat valueMask = hsvChannels[2] > minValue;
hueMask = (hueMask & saturationMask) & valueMask;
cv::imshow("desired color", hueMask);
// now perform the line detection
std::vector<cv::Vec4i> lines;
cv::HoughLinesP(hueMask, lines, 1, CV_PI/360, 50, 50, 10);
// draw the result as big green lines:
for (unsigned int i = 0; i < lines.size(); ++i)
{
cv::line(input, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), cv::Scalar(0, 255, 0), 5);
}
cv::imwrite("C:/StackOverflow/Output/coloredLines_mask.png", hueMask);
cv::imwrite("C:/StackOverflow/Output/coloredLines_detection.png", input);
cv::imshow("input", input);
cv::waitKey(0);
return 0;
}
使用该输入图像:
将解压这个“红”的颜色(调整hueValue
和hueRange
来检测不同的颜色):
和HoughLinesP检测从面罩这些行(应与HoughLines
与此类似):
这里的另一组与非线太图像...
关于您不同的问题:
有两个函数HoughLines和HoughLinesP。 HoughLines不提取线条长度,但可以在后期处理中通过再次检查边缘蒙版(HoughLines输入)的哪些像素对应于提取的线条来计算它。
参数:
图像 - 边缘图像(应该清楚?) 线 - 通过角度和位置,没有长度或某物给定线。它们被无限地解释为 rho - 累加器分辨率。如果线条稍微有些扭曲,则线条越粗糙,但提取的线条的位置/角度的准确性越低 - 阈值越小,误报越少,但您可能会错过某些线条 - 角度分辨率:可以检测到更小,更多不同的线(取决于方向)。如果您的线的方向不符合角度步骤,则线可能不会被检测到。例如,如果CV_PI/180
将在1°
分辨率中检测到,如果您的线路有0.5°
(例如33.5°
),则可能会错过。
我不是那么非常肯定的所有参数,也许你会来看看有关霍夫线检测的文献,或其他人可以在这里添加一些提示。
如果改用cv::HoughLinesP
,有开始和结束点线段将被检测到,这很容易解释,你可以从cv::norm(cv::Point(lines[i][0], lines[i][1]) - cv::Point(lines[i][2], lines[i][3]))
要获取线条的大小,请使用概率霍夫变换。只有超过一定长度的线才会被它检测到。 – FadedCoder
你可以发布(几个)图片吗?解释起来会更容易和更清晰。 – Miki
您的“红色图像”的问题是您无法找到该功能,因为您自己不了解该任务。 “红色”可能不是一个单一的RGB值,而是许多相关的颜色。您想删除所有其他色调并将其替换为黑色。 – MSalters