Опубликован: 20.08.2013 | Уровень: для всех | Доступ: платный | ВУЗ: Новосибирский Государственный Университет
Самостоятельная работа 5:

Сборка и установка Intel® Integrated Performance Primitives. Использование библиотеки в среде Microsoft® Visual Studio

5.3. Схема решения задачи поиска прямых линий на цветном изображении с использованием преобразования Хафа

Схема решения задачи поиска прямых линий на цветном изображении с использованием преобразования Хафа включает несколько этапов:

  1. Загрузка изображения.
  2. Преобразование изображения в оттенки серого.
  3. Поиск ребер на полученном изображении. Ребра можно найти, например, с использованием детектора Канни. Различные способы выделения ребер были рассмотрены в лабораторной работе "Базовые операции обработки изображений".
  4. Применение преобразования Хафа к бинарному изображению, содержащему ребра.
  5. Преобразование полученных параметров прямых из полярной системы координат в декартову систему, связанную с исходным изображением.

5.4. Общая структура приложения и основной функции

Приложение состоит из основной функции и модуля hough_transform, содержащего две функции, которые реализуют поиск прямых линий средствами библиотек Intel® IPP и OpenCV соответственно, а также функцию отображения результирующего набора линий на изображении.

Рассмотрим структуру основной функции. На входе программы имеется цветное изображение, поэтому функция имеет единственный параметр командной строки. Основная функция включает выполнение нескольких действий:

  1. Загрузка исходного изображения с использованием функции imread библиотеки OpenCV.
  2. Вызов функции поиска прямых линий hough_opencv, реализованной в модуле hough_transform, которая выполняет поиск средствами OpenCV.
  3. Вызов функции hough_ipp, также реализованной в модуле hough_transform. Функция выполняет определение прямых линий с использованием преобразования Хафа, реализованного в библиотеке Intel® IPP.
  4. Отображение исходных изображений с отрисованным набором прямых линий.
  5. Освобождение ресурсов, использованных для работы с изображениями.
#include <opencv2/opencv.hpp> 
#include "hough_transform.h" 
 
using namespace cv; 
 
char helper[] = 
"02_IPP_HoughTransform.exe <image>\n\ 
\t<image> - image name\n"; 
 
int main(int argc, char **argv) 
{ 
  Mat srcImgOCV, srcImgIPP, dstImgOCV, dstImgIPP; 
  vector<Point> points1OCV, points2OCV, 
      points1IPP, points2IPP; 
  if (argc < 2) 
  { 
    printf("%s", helper); 
    return 1; 
  } 
 
  // 1. загрузить изображение 
  srcImgOCV = imread(argv[1]); 
  if (srcImgOCV.data == 0) 
  { 
    printf("ERROR!!! imread(...)"); 
    return 1; 
  } 
  srcImgOCV.copyTo(srcImgIPP); 
 
  // 2. поиск прямых средствами OpenCV 
  hough_opencv(srcImgOCV, points1OCV, points2OCV); 
  // 3. поиск прямых средствами IPP 
  hough_ipp(srcImgIPP, points1IPP, points2IPP); 
 
  // 4. отобразить то, что получилось 
  drawLines(srcImgOCV, points1OCV, points2OCV); 
  drawLines(srcImgIPP, points1IPP, points2IPP); 
  namedWindow("OpenCV"); 
  imshow("OpenCV", srcImgOCV); 
  namedWindow("IPP"); 
  imshow("IPP", srcImgIPP); 
  waitKey(); 
  // 5. освободить память 
  srcImgOCV.release(); 
  srcImgIPP.release(); 
  dstImgOCV.release(); 
  dstImgIPP.release(); 
  return 0; 
}   
    

5.5. Реализация поиска прямых с использованием функций библиотеки OpenCV

Перейдем к рассмотрению функции hough_opencv. Функция принимает в качестве входных параметров исходное изображение srcImg и два вектора точек points1 и points2, каждая пара определяет прямую линию.

В начале блока функции объявим необходимые переменные.

int hough_opencv(const Mat &srcImg, 
    vector<Point> &points1, vector<Point> &points2) 
{ 
  Mat edges, grayImg; 
  vector<Vec2f> lines; 
  double threshold1 = 50, threshold2 = 200, 
      rhoStep = 1, thetaStep = CV_PI / 180; 
  int houghThreshold = 100, kLines, i;   
    

Затем выполним преобразование цветного изображения в оттенки серого посредствам вызова функции cvtColor.

  cvtColor(srcImg, grayImg, CV_RGB2GRAY);   
    

Для полученного полутонового изображения выполним поиск ребер на изображении с использованием детектора Канни. Схема работы алгоритма Канни и описание параметров соответствующей функции библиотеки OpenCV было приведено в лабораторной работе "Базовые операции обработки изображений". Дополнительно выполним отображение бинарного изображения ребер.

  Canny(grayImg, edges, threshold1, threshold2); 
  namedWindow("Canny (OpenCV)"); 
  imshow("Canny (OpenCV)", edges);   
    

Далее к бинарному изображению, содержащему ребра, применим преобразование Хафа посредствам вызова функции HoughLines. Функция принимает следующий набор параметров:

  1. edges – исходное бинарное изображение ребер.
  2. lines – результирующий вектор прямых линий.
  3. rhoStep – шаг дискретизации сетки по радиусу.
  4. thetaStep – шаг дискретизации по углу наклона перпендикуляра.
  5. houghThreshold – порог, по которому выполняется отсечение ячеек (фактически минимальное количество точек в ячейке, чтобы линия с соответствующими параметрами была продетектирована).
  HoughLines(edges, lines, rhoStep, thetaStep, 
    houghThreshold);   
    

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

  kLines = lines.size(); 
  for (i = 0; i < kLines; i++) 
  { 
    float rho = lines[i][0], theta = lines[i][1]; 
    Point pt1, pt2; 
    double cosTheta = cos(theta), 
      sinTheta = sin(theta); 
    double x0 = cosTheta * rho, y0 = sinTheta * rho; 
    pt1.x = cvRound(x0 + 1000 * (-sinTheta)); 
    pt1.y = cvRound(y0 + 1000 * cosTheta); 
    pt2.x = cvRound(x0 - 1000 * (-sinTheta)); 
    pt2.y = cvRound(y0 - 1000 * cosTheta); 
    points1.push_back(pt1); 
    points2.push_back(pt2); 
  } 
  grayImg.release(); 
  edges.release(); 
  return 0; 
}   
    
Александра Максимова
Александра Максимова

При прохождении теста 1 в нем оказались вопросы, который во-первых в 1 лекции не рассматривались, во-вторых, оказалось, что вопрос был рассмаотрен в самостоятельно работе №2. Это значит, что их нужно выполнить перед прохождением теста? или это ошибка?
 

Алена Борисова
Алена Борисова

В лекции по обработке полутоновых изображений (http://www.intuit.ru/studies/courses/10621/1105/lecture/17979?page=2) увидела следующий фильтр:


    \begin{array}{|c|c|c|}
    \hline \\
    0 & 0 & 0 \\
    \hline \\
    0 & 2 & 0 \\
    \hline \\
    0 & 0 & 0 \\
    \hline 
    \end{array} - \frac{1}{9} \begin{array}{|c|c|c|}
    \hline \\
    0 & 0 & 0 \\
    \hline \\
    0 & 1 & 0 \\
    \hline \\
    0 & 0 & 0 \\
    \hline 
    \end{array}

В описании говорится, что он "делает изображение более чётким, потому что, как видно из конструкции фильтра, в однородных частях изображение не изменяется, а в местах изменения яркости это изменение усиливается".

Что вижу я в конструкции фильтра (скорее всего ошибочно): F(x, y) = 2 * I(x, y) - 1/9 I(x, y) = 17/9 * I(x, y), где F(x, y) - яркость отфильтрованного пикселя, а I(x, y) - яркость исходного пикселя с координатами (x, y). Что означает обычное повышение яркости изображения, при этом без учета соседних пикселей (так как их множители равны 0).

Объясните, пожалуйста, как данный фильтр может повышать четкость изображения?

Сергей Кротов
Сергей Кротов
Россия
Дмитрий Донсков
Дмитрий Донсков
Россия, Москва, Московский Авиационный Институт