Добрый день!
Изучаю OpenCV очень недавно, но требуется решить задачу распознавания знаков ограничения скорости.
Решил попробовать вариант сравнения с шаблоном, но у меня возникает проблема:
сначала я использую детектор границ Canny и он довольно хорошо находит нужные мне окружности(рамка знака ограничения скорости).
Но когда я по примеру для похожей задачи хочу выделить контуры и залить их белым(для маски, чтобы в последующем сравнить её с исходным изображением),
контурами рамка обводится плохо и нет возможности сделать из неё маску. Подскажите, пожалуйста, что можно сделать в данной ситуации? И как можно было бы очистить изображение от мелких объектов?
Идея такая - исходное изображение я конвертирую в HSV палитру и разбиваю на отдельные каналы. Для каждого канала есть свои ползунки, чтобы подобрать оптимальное значение( экспериментально и через статьи в интернете оптимальными явились Hue [170,255], Sat[100,255], Val[100,255]). Это параметры для красного цвета, чтобы в последующем выделить рамку знака.
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <cv.h>
#include <highgui.h>
#include <cxcore.h>
IplImage* image = 0;
IplImage* dst = 0;
// для хранения каналов HSV
IplImage* hsv = 0;
IplImage* h_plane = 0;
IplImage* s_plane = 0;
IplImage* v_plane = 0;
// для хранения каналов HSV после преобразования
IplImage* h_range = 0;
IplImage* s_range = 0;
IplImage* v_range = 0;
// для хранения суммарной картинки
IplImage* hsv_and = 0;
//Для хранения контуров
IplImage* contoured=0;
//Маска
IplImage* mask=0;
//Между кенни и контуром
IplImage* cont=0;
int Hmin = 0;
int Hmax = 256;
int Smin = 0;
int Smax = 256;
int Vmin = 0;
int Vmax = 256;
int HSVmax = 256;
//
// функции-обработчики ползунков
//
void myTrackbarHmin(int pos) {
Hmin = pos;
cvInRangeS(h_plane, cvScalar(Hmin), cvScalar(Hmax), h_range);
}
void myTrackbarHmax(int pos) {
Hmax = pos;
cvInRangeS(h_plane, cvScalar(Hmin), cvScalar(Hmax), h_range);
}
void myTrackbarSmin(int pos) {
Smin = pos;
cvInRangeS(s_plane, cvScalar(Smin), cvScalar(Smax), s_range);
}
void myTrackbarSmax(int pos) {
Smax = pos;
cvInRangeS(s_plane, cvScalar(Smin), cvScalar(Smax), s_range);
}
void myTrackbarVmin(int pos) {
Vmin = pos;
cvInRangeS(v_plane, cvScalar(Vmin), cvScalar(Vmax), v_range);
}
void myTrackbarVmax(int pos) {
Vmax = pos;
cvInRangeS(v_plane, cvScalar(Vmin), cvScalar(Vmax), v_range);
}
int main(int argc, char* argv[])
{
image=cvLoadImage("D:\\1.jpg",1);
//Создание картинок
hsv=cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,3);
h_plane = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
s_plane = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
v_plane = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
h_range = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
s_range = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
v_range = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
hsv_and = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
contoured=cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
mask=cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
cont=cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
//Создание маски, заливка изображения чёрным
cvSet(mask,cvScalar(0,0,0));
//Конвертируем в HSV
cvCvtColor(image,hsv,CV_BGR2HSV);
//Разбиваем на отдельные каналы
cvCvtPixToPlane(hsv, h_plane,s_plane,v_plane,0);
//определим max и min значение HSV каналов
double framemin=0;
double framemax=0;
cvMinMaxLoc(h_plane,&framemin,&framemax);
printf("[H] %f x %f\n",framemin,framemax);
Hmin=framemin;
Hmax=framemax;
cvMinMaxLoc(s_plane,&framemin,&framemax);
printf(" %f x %f\n",framemin,framemax);
Smin=framemin;
Smax=framemax;
cvMinMaxLoc(v_plane,&framemin,&framemax);
printf("[V] %f x %f\n",framemin,framemax);
Vmin=framemin;
Vmax=framemax;
//Отображение изображений
cvNamedWindow("original",CV_WINDOW_AUTOSIZE);
cvNamedWindow("H range",CV_WINDOW_AUTOSIZE);
cvNamedWindow("S range",CV_WINDOW_AUTOSIZE);
cvNamedWindow("V range",CV_WINDOW_AUTOSIZE);
cvNamedWindow("Contoured",CV_WINDOW_AUTOSIZE);
cvNamedWindow("Mask",CV_WINDOW_AUTOSIZE);
cvNamedWindow("Canny",CV_WINDOW_AUTOSIZE);
cvCreateTrackbar("Hmin","H range", &Hmin, HSVmax, myTrackbarHmin);
cvCreateTrackbar("Hmax","H range", &Hmax, HSVmax,myTrackbarHmax);
cvCreateTrackbar("Smin","S range",&Smin,HSVmax,myTrackbarSmin);
cvCreateTrackbar("Smax","S range",&Smax,HSVmax,myTrackbarSmax);
cvCreateTrackbar("Vmin","V range",&Vmin,HSVmax,myTrackbarVmin);
cvCreateTrackbar("Vmax","V range",&Vmax,HSVmax,myTrackbarVmax);
while(1){
//отображаем изображение
cvShowImage("original",image);
cvShowImage("H range",h_range);
cvShowImage("S range",s_range);
cvShowImage("V range",v_range);
//складываем
cvAnd(h_range,s_range,hsv_and);
cvAnd(hsv_and,v_range,hsv_and);
//Выделение контура
cvCanny(hsv_and,cont,50,255,5);
// хранилище памяти
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contours = 0;
//Поиск контура
cvFindContours(cont,storage,&contours,sizeof(CvContour),CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
// рисуем найденный контур НА маске и заливаем его белым
cvDrawContours(mask,contours, CV_RGB(255,255,255),CV_RGB(255,255,255), 0, CV_FILLED, CV_AA, cvPoint(0,0));
cvShowImage("Canny",cont);
cvShowImage("Contoured", hsv_and);
cvShowImage("Mask", mask);
char c=cvWaitKey(33);
if (c==27){
break;
}
}
// освобождаем ресурсы
cvReleaseImage(&image);
cvReleaseImage(&hsv);
cvReleaseImage(&h_range);
cvReleaseImage(&s_range);
cvReleaseImage(&v_range);
cvReleaseImage(&hsv_and);
cvReleaseImage(&contoured);
cvReleaseImage(&mask);
cvReleaseImage(&cont);
// удаляем окна
cvDestroyAllWindows();
return 0;
}
Скриншоты исходного изображения, изображения после поиска границ Кенни и контура прилагаются.
1. Исходное
2. Детектор границ Кенни
3. Поиск контура
Буду премного благодарен Вам всем за помощь!