А почему на вход cvThreshold() должны поступать только изображения в градациях серого?
на вход cvThreshold должно поступать одноканальное изображение (да — градации серого, т.е. яркости)
всё логично, т.к. пороговое преобразование работает с яркостью.
Разумеется можно обработать и цветную RGB-картинку:
для этого её сначала придётся разбить на слои (cvSplit()),
проделать пороговое преобразование над каждым слоем,
сложить слои вместе (cvMerge())
Дополним пример 21 шага работой с RGB-слоями:
// // пример порогового преобразования над RGB-картинкой // cvThreshold() и cvAdaptiveThreshold() // // robocraft.ru // #include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char* argv[]) { IplImage *image=0, *gray=0, *dst=0, *dst2=0; IplImage* r=0, *g=0, *b=0; // для хранения отдельных слоёв RGB-изображения // имя картинки задаётся первым параметром char* filename = argc >= 2 ? argv[1] : "Image0.jpg"; // получаем картинку image = cvLoadImage(filename, 1); printf("[i] image: %s\n", filename); assert( image != 0 ); // покажем изображение cvNamedWindow( "original", 1 ); cvShowImage( "original", image ); // картинка для хранения изображения в градациях серого gray = cvCreateImage(cvGetSize(image), image->depth, 1); // преобразуем картинку в градации серого cvConvertImage(image, gray, CV_BGR2GRAY); // покажем серую картинку cvNamedWindow( "gray", 1 ); cvShowImage( "gray", gray ); dst = cvCreateImage( cvGetSize(gray), IPL_DEPTH_8U, 1); dst2 = cvCreateImage( cvGetSize(gray), IPL_DEPTH_8U, 1); // пороговые преобразования над картинкой в градациях серого cvThreshold(gray, dst, 50, 250, CV_THRESH_BINARY); cvAdaptiveThreshold(gray, dst2, 250, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, 1); // показываем результаты cvNamedWindow( "cvThreshold", 1 ); cvShowImage( "cvThreshold", dst); cvNamedWindow( "cvAdaptiveThreshold", 1 ); cvShowImage( "cvAdaptiveThreshold", dst2); //======================================================= // // проведём пороговое преобразование над RGB-картинкой // r = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1); g = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1); b = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1); // разбиваем на отдельные слои cvSplit(image, b, g, r, 0); // картинка для хранения промежуточных результатов IplImage* temp = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); // складываем картинки с одинаковым весом cvAddWeighted( r, 1.0/3.0, g, 1.0/3.0, 0.0, temp ); cvAddWeighted( temp, 2.0/3.0, b, 1.0/3.0, 0.0, temp ); // выполняем пороговое преобразование cvThreshold(temp, dst, 50, 250, CV_THRESH_BINARY); cvReleaseImage(&temp); // показываем результат cvNamedWindow( "RGB cvThreshold", 1 ); cvShowImage( "RGB cvThreshold", dst); // // попробуем пороговое преобразование над отдельными слоями // IplImage* t1, *t2, *t3; // для промежуточного хранения t1 = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1); t2 = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1); t3 = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1); // выполняем пороговое преобразование cvThreshold(r, t1, 50, 250, CV_THRESH_BINARY); cvThreshold(g, t2, 50, 250, CV_THRESH_BINARY); cvThreshold(b, t3, 50, 250, CV_THRESH_BINARY); // складываем результаты cvMerge(t3, t2, t1, 0, image); cvNamedWindow( "RGB cvThreshold 2", 1 ); cvShowImage( "RGB cvThreshold 2", image); cvReleaseImage(&t1); cvReleaseImage(&t2); cvReleaseImage(&t3); //======================================================= // ждём нажатия клавиши cvWaitKey(0); // освобождаем ресурсы cvReleaseImage(& image); cvReleaseImage(&gray); cvReleaseImage(&dst); cvReleaseImage(&dst2); cvReleaseImage(&r); cvReleaseImage(&g); cvReleaseImage(&b); // удаляем окна cvDestroyAllWindows(); return 0; }
результат работы:
2 комментария на «“Вопросы OpenCV — пороговое преобразование над цветной картинкой”»
Добрый день!
Неправильно отрабатывает CV_BGR2GRAY. Что у меня не так? Спасибо:)
InitializeComponent();
cv::Mat bmp1 = cv::imread(«demo.jpg»);
cv::Mat bmp2 = cv::Mat(bmp1.rows, bmp1.cols, CV_BGR2GRAY);
cv::cvtColor(bmp1, bmp2, CV_BGR2GRAY);
WriteableBitmap^ wbmp = ref new WriteableBitmap(bmp2.cols, bmp2.rows);
IBuffer^ buffer = wbmp->PixelBuffer;
unsigned char* dstPixels;
ComPtrpBufferByteAccess;
ComPtrpBuffer((IInspectable*)buffer);
pBuffer.As(&pBufferByteAccess);
pBufferByteAccess->Buffer(&dstPixels);
memcpy(dstPixels, bmp2.data, bmp2.step.buf[1] * bmp2.cols * bmp2.rows);
image1->Source = wbmp;