Vicul 0 Жалоба Опубликовано July 30, 2009 Всем привет, изучаю пакет OpenCV по книге О'Релли "OpenCV..." и не могу сделать одно упражнение ***************** Separable kernels. Create a 3-by-3 Gaussian kernel using rows [(1/16, 2/16, 1/16), (2/16, 4/16, 2/16), (1/16, 2/16, 1/16)] and with anchor point in the middle. a. Run this kernel on an image and display the results. b. Now create two one-dimensional kernels with anchors in the center: one going “across” (1/4, 2/4, 1/4), and one going down (1/4, 2/4, 1/4). Load the same original image and use cvFilter2D() to convolve the image twice, once with the first 1D kernel and once with the second 1D kernel. Describe the results. ************************ я сделал три этих фильтра, но они не меняют исходное изображение, уже сижу третий день не могу найти где ошибка. Вот мой код IplImage* src = cvLoadImage("4.jpg"); cvNamedWindow("src", 1); cvShowImage("src", src); IplImage* rgb[3]; float L45[]={ 1./16., 2./16., 1./16., 2./16., 4./16., 2./16., 1./16., 2./16., 1./16.};// CvMat* rgbMat = cvCreateMat(3, 3, CV_32FC1); for (int y = 0; y < 3; y++) { for (int x = 0; x < 3; x++) cvmSet(rgbMat, y, x, L45[y*3 + x]); } IplImage* dst = cvCreateImage(cvSize(src->width, src->height), src->depth, 3); IplImage* dstRGB[3]; for (int i = 0; i < 3; i++) { rgb = cvCreateImage(cvSize(src->width, src->height), src->depth, 1); dstRGB = cvCreateImage(cvSize(src->width, src->height), src->depth, 1); } cvSplit(src, rgb[0], rgb[1], rgb[2], NULL); for (int i = 0; i < 3; i++) { cvFilter2D(rgb, dstRGB, rgbMat); } cvReleaseMat(&rgbMat); cvMerge(dstRGB[0], dstRGB[1], dstRGB[2], NULL, dst); cvNamedWindow("dst", 1); cvShowImage("dst", dst); //across float D[] = {1./4., 2./4., 1./4.}; rgbMat = cvCreateMat(1, 3, CV_32FC1); for (int x = 0; x < 3; x++) cvmSet(rgbMat, 0, x, D[x]); for (int i = 0; i < 3; i++) { cvZero(dstRGB); cvFilter2D(rgb, dstRGB, rgbMat, cvPoint(1, 0)); } cvReleaseMat(&rgbMat); cvZero(dst); cvMerge(dstRGB[0], dstRGB[1], dstRGB[2], NULL, dst); cvNamedWindow("Across", 1); cvShowImage("Across", dst); //down rgbMat = cvCreateMat(3, 1, CV_32FC1); for (int y = 0; y < 3; y++) cvmSet(rgbMat, y, 0, D[y]); for (int i = 0; i < 3; i++) { cvZero(dstRGB); cvFilter2D(rgb, dstRGB, rgbMat, cvPoint(0, 1)); } cvReleaseMat(&rgbMat); cvZero(dst); cvMerge(dstRGB[0], dstRGB[1], dstRGB[2], NULL, dst); cvNamedWindow("Down", 1); cvShowImage("Down", dst); cvReleaseImage(&dst); for (int i = 0; i < 3; i++) { cvReleaseImage(&rgb); cvReleaseImage(&dstRGB); } cvWaitKey(0); cvReleaseImage(&src); cvDestroyWindow("src"); cvDestroyWindow("dst"); cvDestroyWindow("Across"); cvDestroyWindow("Down"); Буду благодарен за любую идею в этом вопросе. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано July 30, 2009 Вот проект вычисления скелета изображения (тема есть на форуме), там как раз свертка применяется и все работает, посмотрите, если будут вопросы, задавайте: http://www.compvision.ru/forum/index.php?a...=post&id=55 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Vicul 0 Жалоба Опубликовано July 30, 2009 Вот проект вычисления скелета изображения (тема есть на форуме Спасибо за инфу, помоему это единственный форум, где я нашел единомышленников. С градусными коэффициентами с Вашего проекта у меня все работает (в книге это предыдущее задание). У меня большие сомнения в моих исходных коэф-тах - [(1/16, 2/16, 1/16), (2/16, 4/16, 2/16), (1/16, 2/16, 1/16)] и (1/4, 2/4, 1/4). Я их тупо впихиваю в матрицу. Интуиция мне подсказывает здесь необходима дополнительная обработка, ведь не зря они написали "Separable kernels". Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано July 30, 2009 Спасибо за инфу, помоему это единственный форум, где я нашел единомышленников. С градусными коэффициентами с Вашего проекта у меня все работает (в книге это предыдущее задание). У меня большие сомнения в моих исходных коэф-тах - [(1/16, 2/16, 1/16), (2/16, 4/16, 2/16), (1/16, 2/16, 1/16)] и (1/4, 2/4, 1/4). Я их тупо впихиваю в матрицу. Интуиция мне подсказывает здесь необходима дополнительная обработка, ведь не зря они написали "Separable kernels". Вот здесь статейка о разделяемых ядрах. Насколько я понял, разделяемым называется двумерное ядро свертки, которое можно представить в виде матричного произведения одномерных ядер. Из этого следует, что применение двумерного ядра эквивалентно последовательному применению к изображению одномерных ядер, являющихся множителями на которые раскладывается исходная матрица. То есть, я предполагаю (считать лень), что квадратная матрица [(1/16, 2/16, 1/16), (2/16, 4/16, 2/16), (1/16, 2/16, 1/16)], есть матричное произведение двух одномерных матриц строки (1/4, 2/4, 1/4) и столбца (1/4, 2/4, 1/4). И результат после применения 2Д ядра свертки, и после последовательного применения 1Д ядер свертки результат должен быть одинаковый. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Vicul 0 Жалоба Опубликовано July 30, 2009 Вот здесь статейка о разделяемых ядрах. Линк у меня не работает, можно повторить. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано July 30, 2009 Линк у меня не работает, можно повторить. Вот: http://blogs.mathworks.com/steve/2006/10/0...le-convolution/ И сверху поправил. Кстати, ядро из примера, это размытие, его действие сложно заметить. Я переделал на оператор Собеля все работает. У меня посл. свертка работает (собель из статьи выше): //--------------------------------------------------------------------------- void ProcessFrame( IplImage* src ) { IplImage* rgb[3]; CvMat* rgbMat; IplImage* dst = cvCreateImage(cvSize(src->width, src->height), src->depth, 3); IplImage* dstRGB[3]; for (int i = 0; i < 3; i++) { rgb = cvCreateImage(cvSize(src->width, src->height), src->depth, 1); dstRGB = cvCreateImage(cvSize(src->width, src->height), src->depth, 1); } cvSplit(src, rgb[0], rgb[1], rgb[2], NULL); //across float D[] = {1, 2, 1}; // Первая часть ядра rgbMat = cvCreateMat(1, 3, CV_32FC1); for (int x = 0; x < 3; x++) cvmSet(rgbMat, 0, x, D[x]); for ( i = 0; i < 3; i++) { cvZero(dstRGB); cvFilter2D(rgb, dstRGB, rgbMat, cvPoint(1, 0)); } cvReleaseMat(&rgbMat); cvZero(dst); cvMerge(dstRGB[0], dstRGB[1], dstRGB[2], NULL, dst); //down rgbMat = cvCreateMat(3, 1, CV_32FC1); D[0]=-1; // Вторая часть ядра D[1]=0; D[2]=1; for (int y = 0; y < 3; y++) cvmSet(rgbMat, y, 0, D[y]); for ( i = 0; i < 3; i++) { // cvZero(dstRGB); cvFilter2D(dstRGB, dstRGB, rgbMat, cvPoint(0, 1)); // и здесь поправил (чтобы фильтры последовательно применялись) } cvReleaseMat(&rgbMat); cvZero(dst); cvMerge(dstRGB[0], dstRGB[1], dstRGB[2], NULL, dst); for ( i = 0; i < 3; i++) { cvReleaseImage(&rgb); cvReleaseImage(&dstRGB); } APIDrawIpl(10,10,src,Form1->Handle); APIDrawIpl(400,10,dst,Form1->Handle); cvReleaseImage(&dst); } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Vicul 0 Жалоба Опубликовано July 30, 2009 Спасибо за линк, теперь более менее понятно Вот: Кстати Тут по моему нестыковочка: for (int x = 0; x < 3; x++) cvmSet(rgbMat, 0, x, D[x]); // здесь 0,x for (int i = 0; i < 3; i++) { cvZero(dstRGB); cvFilter2D(rgb, dstRGB, rgbMat, cvPoint(1, 0)); // а якорь здесь cvPoint(1, 0) } Помоему здесь все в норьме. cvmSet() берет вторым параметром ряды y (у нас их 1, нулевой)и три значения столбцов x. Ну а якорь идет по определению CvPoint(int x, int y), т.е (1,0) указывает на центр . В принципе его можно не указывать, оставить по умолчанию, это я уже потом его прилепил для успокоения совести. Ладно, вопрос остается, почему все эти три фильтра не меняют картинку? Т.е, 1. Пропускаем через cvFilter2D(src, ... ) матрицу [(1/16, 2/16, 1/16), (2/16, 4/16, 2/16), (1/16, 2/16, 1/16)]. Допустим эта матрица ничего не меняет. 2. Тогда используем через cvFilter2D(src, ... ) одноядерную матрицу по горизонтале (1/4, 2/4, 1/4). Должно же что-то поменяться? 3. А вот теперь если пропустить через полученный результат вертикальную матрицу мы должны получить результат для п.1., ведь если перемножить две одноядеорные матрицы, то мы получим первый фильтр. Резюмирую. Хоть в одном из трех случаев cvFilter2D() должен был изменить изображения. У меня все одиноковое. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Vicul 0 Жалоба Опубликовано July 30, 2009 > float D[] = {1, 2, 1}; Да если поставить эти коэф-ты, то будет что-то меняться, но у меня они дробные. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано July 30, 2009 > float D[] = {1, 2, 1}; Да если поставить эти коэф-ты, то будет что-то меняться, но у меня они дробные. На всякий случай перевел все на float. //--------------------------------------------------------------------------- void ProcessFrame( IplImage* img ) { IplImage* rgb[3]; CvMat* rgbMat; IplImage* dst = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, 3); IplImage* src = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, 3); cvConvert(img,src); IplImage* dstRGB[3]; for (int i = 0; i < 3; i++) { rgb = cvCreateImage(cvSize(src->width, src->height), IPL_DEPTH_32F, 1); dstRGB = cvCreateImage(cvSize(src->width, src->height), IPL_DEPTH_32F, 1); } cvSplit(src, rgb[0], rgb[1], rgb[2], NULL); //across float D[] = {0.25, 0.5, 0.25}; rgbMat = cvCreateMat(1, 3, CV_32FC1); for (int x = 0; x < 3; x++) cvmSet(rgbMat, 0, x, D[x]); for ( i = 0; i < 3; i++) { cvZero(dstRGB); cvFilter2D(rgb, dstRGB, rgbMat); } cvReleaseMat(&rgbMat); //down rgbMat = cvCreateMat(3, 1, CV_32FC1); cvZero(dst); cvMerge(dstRGB[0], dstRGB[1], dstRGB[2], NULL, dst); for (int y = 0; y < 3; y++) cvmSet(rgbMat, y, 0, D[y]); for ( i = 0; i < 3; i++) { // cvZero(dstRGB); cvFilter2D(dstRGB, dstRGB, rgbMat, cvPoint(0, 1)); // è çäåñü ïîïðàâèë (÷òîáû ôèëüòðû ïîñëåäîâàòåëüíî ïðèìåíÿëèñü) } cvReleaseMat(&rgbMat); cvZero(dst); cvMerge(dstRGB[0], dstRGB[1], dstRGB[2], NULL, dst); //cvConvertScale( dst, dst,25000,0); APIDrawIpl(10,10,src,Form1->Handle); APIDrawIpl(400,10,dst,Form1->Handle); cvZero(dst); for ( i = 0; i < 3; i++) { cvReleaseImage(&rgb); cvReleaseImage(&dstRGB); } cvReleaseImage(&src); cvReleaseImage(&dst); } Вообще-то разница (правое немного размыто) есть: Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Vicul 0 Жалоба Опубликовано July 31, 2009 Вообще-то разница (правое немного размыто) есть: Хрен его знает, избражение почти не меняется, я пытался сравнивать данные в матрицах изображений, вначале все одинаково. Далее идти - можно "резьбу сорвать". Думаю коэф-ты ядер слишком маленькие, чтобы визуально что-то определить. В принципе идея понятна, вопрос закрыт, спасибо за помощь. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах