OpenCV: как обнаружить линии определенного цвета?

Я работаю над небольшим проектом OpenCV, чтобы обнаружение линий определенного цвета с камеры мобильного телефона.

Короче хотел бы:

  1. Преобразовать входное изображение в изображение определенного цвета (например, красный из определенного верхнего и нижнего диапазона)
  2. Примените преобразование линии Хафа к полученному изображению, чтобы оно обнаруживало только линии этого определенного цвета.
  3. Наложить на исходное изображение обнаруженные линии

Это те функции, которые я хотел бы использовать, но не уверен, как заполнить пропущенные биты.

Это функция processImage, вызываемая из приложение для смартфона при обработке изображений из экземпляра CvVideoCamera

- (void)processImage:(Mat&)image;
{
cv::Mat orig_image = image.clone();

cv::Mat red_image = ??

// Apply houghes transformation to detect lines between a minimum length and a maximum length (I was thinking of using the CV_HOUGH_PROBABILISTIC method..)
// Comment.. see below..

Я не могу понять документация здесь как C ++
Подпись метода не имеет поля метода

vector<Vec2f> lines;

Из официальной документации:

C ++: void HoughLines (изображение InputArray, строки OutputArray, двойное rho, двойное тэта, порог int, двойное srn = 0, двойное stn = 0)

HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );

Взятые из примера кода, не поняли должным образом, как это работает ..

(например, что такое использование тета? Как дать другой угол
отразить в обнаружении линии?)

for( size_t i = 0; i < lines.size(); i++ )
{

Здесь я должен рассматривать только строки выше определенного размера .. (не знаю, как)

}

Здесь я должен затем добавить результирующие строки к исходному изображению (не знаю, как), чтобы они могли быть показаны на экране ..

Любая помощь будет принята с благодарностью.

2

Решение

Вы можете использовать цветовое пространство 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 так же):

введите описание изображения здесь

Вот еще один набор изображений с нелинейными линиями тоже …

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

О ваших разных вопросах:

  1. Есть две функции HoughLines и HoughLinesP. HoughLines не извлекает длину строки, но вы можете вычислить ее в постобработке, снова проверив, какие пиксели маски края (входные данные HoughLines) соответствуют извлеченной строке.

  2. параметры:

    изображение — край изображения (должно быть ясно?)
    линии — линии, заданные углом и положением, без длины или чч. они интерпретируются бесконечно долго
    rho — разрешение аккумулятора. Чем больше, тем надежнее в случае слегка искаженных линий должно быть, но менее точно в положении / угле извлеченных линий
    Порог — чем больше, тем меньше ложных срабатываний, но вы можете пропустить некоторые строки
    тета — угловое разрешение: чем меньше, тем больше разных линий (в зависимости от ориентации) можно обнаружить. Если ориентация вашей линии не соответствует угловым шагам, линия может быть не обнаружена. Например, если вы CV_PI/180 обнаружит в разрешение, если ваша строка имеет 0.5° (например. 33.5°) ориентация, это может быть пропущено.

Я не очень уверен во всех параметрах, возможно, вам придется взглянуть на литературу по обнаружению сильных линий, или кто-то еще может добавить некоторые подсказки здесь.

Если вы вместо этого используете cv::HoughLinesPбудут обнаружены отрезки линии с начальной и конечной точкой, что проще для интерпретации, и вы можете вычислить длину линии из cv::norm(cv::Point(lines[i][0], lines[i][1]) - cv::Point(lines[i][2], lines[i][3]))

6

Другие решения

Я не буду показывать код, но шаги с некоторыми хитростями.

Предположим, что вы хотите обнаружить дорожные полосы (это линии белого или светло-желтого цвета, имеющие определенные свойства).

Исходное изображение(Я добавляю несколько дополнительных строк, чтобы шуметь)

введите описание изображения здесь

Шаг 1: Удалите части изображения, которые не нужно использовать, сохраните загрузку процессора (просто, но полезно)

введите описание изображения здесь

Шаг 2: Преобразовать в серое изображение

введите описание изображения здесь

Шаг 3: порог

Используя порог в соответствии с цветом вашей линии, цвет станет белым, а другие станут черными

введите описание изображения здесь

Шаг 4: Использование контуров для нахождения границ объектов

введите описание изображения здесь

Шаг 5: Использование Fitline с Контурами на предыдущем шаге является вводом для возврата уравнений линий

Fitline возвращает (x0, y0) и вектор v = (a, b)

введите описание изображения здесь

Шаг 6: С помощью уравнений линий вы можете нарисовать любую нужную вам линию

введите описание изображения здесь

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector