Вопросы OpenCV — пороговое преобразование над цветной картинкой


А почему на вход 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;
}

скачать иходник (qa1.cpp)

результат работы:


2 комментария на «“Вопросы OpenCV — пороговое преобразование над цветной картинкой”»

  1. Добрый день!
    Неправильно отрабатывает 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;

    • cv::Mat color = cv::imread(filename, CV_LOAD_IMAGE_COLOR); // загрузка цветной картинки в формате BGR
      cv::Mat gray(color.size(), CV_8UC1);
      cv::cvtColor(color, gray, CV_BGR2GRAY);
      

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Arduino Bluetooth CraftDuino DIY Google IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение