Определение определенного (качественного) цвета в видео с помощью OpenCV

Итак: у меня есть эта программа OpenCV, которая захватывает видео с камеры и отображает его в двух окнах. Один не имеет определения цвета; другой выделяет определенные конкретные цвета (например, красный).

Что мне нужно, так это способ выяснить, содержит ли изображение в определенный момент этот конкретный цвет. Прямо сейчас, первое окно — просто обычный вывод видео. Второе окно полностью черное до тех пор, пока не будет замечен объект, соответствующий указанному мной цвету, из-за чего объект будет отображаться белым во втором окне.

Я хочу знать, когда он обнаружен, а затем вывести «обнаружен» или «не обнаружен».

Как мне это сделать? Я подумал, что перебрал бы ширину и высоту измененного изображения, а затем проверил, но я понятия не имею, как это сделать. Любая помощь приветствуется — я уже несколько дней пытаюсь найти ответ на этот вопрос, но безуспешно. Я проверил StackOverflow, но он не дал мне то, что мне нужно. Спасибо!

КОД:

#include <opencv/cv.h>
#include <opencv/highgui.h>

//This function threshold the HSV image and create a binary image
IplImage* GetThresholdedImage(IplImage* imgHSV){
IplImage* imgThresh=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
IplImage* imgThresh2=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
IplImage* imgThresh3=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
cvInRangeS(imgHSV, cvScalar(170,160,60), cvScalar(180,256,256), imgThresh2);
cvInRangeS(imgHSV, cvScalar(0,160,60), cvScalar(22,256,256), imgThresh3);
cvOr(imgThresh2, imgThresh3, imgThresh);
cvInRangeS(imgHSV, cvScalar(75,160,60), cvScalar(130,256,256), imgThresh3);
cvOr(imgThresh, imgThresh3, imgThresh);
return imgThresh;
}

int main(){
CvCapture* capture =0;

capture = cvCaptureFromCAM(0);
if(!capture){
printf("Capture failure\n");
return -1;
}

IplImage * frame = 0;

cvNamedWindow("Video");
cvNamedWindow("Ball");//iterate through each frames of the video
while(true){

frame = cvQueryFrame(capture);
if(!frame) break;

frame=cvCloneImage(frame);
cvSmooth(frame, frame, CV_GAUSSIAN,3,3); //smooth the original image using Gaussian kernel

IplImage* imgHSV = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
cvCvtColor(frame, imgHSV, CV_BGR2HSV); //Change the color format from BGR to HSV

IplImage* imgThresh = GetThresholdedImage(imgHSV);

cvSmooth(imgThresh, imgThresh, CV_GAUSSIAN,3,3); //smooth the binary image using Gaussian kernel

cvShowImage("Ball", imgThresh);
cvShowImage("Video", frame);
int sum = 0;
for (int i = 0; i < imgThresh->width; i++) {
for (int j = 0; j < imgThresh->height; j++) {
// WHAT DO I NEED HERE TO CALCULATE CERTAIN COLOR
}
}
if (sum > 1) { cout >> "Detected"; }
else { cout >> "Not Detected"; }

//Clean up used images
cvReleaseImage(&imgHSV);
cvReleaseImage(&imgThresh);
cvReleaseImage(&frame);

//Wait 50mS
int c = cvWaitKey(10);
//If 'ESC' is pressed, break the loop
if((char)c==27 ) break;
}

cvDestroyAllWindows() ;
cvReleaseCapture(&capture);

return 0;
}

1

Решение

Обработка изображений не является точной наукой, и решение зависит от входных данных …

  • Если вы используете изображения, созданные цифровым способом, вы можете посчитать положительные пиксели, используя cvCountNonZero на отфильтрованном изображении
  • Если ваши изображения являются реальными снимками, то есть вероятность, что у любого данного изображения есть по крайней мере несколько пикселей в цветах вашего фильтра. Подсчет пикселей в локализованном скользящем окне может работать лучше, но это, конечно, не единственный подход. Например, возьмите область между координатами (0,0) — (100,100) и посчитайте количество ненулевых. Если это превышает определенное число, предположим, что у вас есть положительный результат. В противном случае продолжайте для перекрывающегося окна (0,50) до (100, 150) …
0

Другие решения

Вы можете циклически проходить по строкам и столбцам изображения, а если значение красного больше некоторого порога, вы можете установить соответствующие пиксели в другом кадре в белый цвет. Также я не написал это в следующем коде, но вы также можете установить пороговые значения для зеленого и синего. Потому что, если объект, который вы ищете, красный, он будет низко в зеленой и синей записях.

#include <opencv/cv.h>
#include <opencv/highgui.h>
//#include <opencv/imgproc.h>
#include <iostream>

using namespace std;

//This function threshold the HSV image and create a binary image
IplImage* GetThresholdedImage(IplImage* imgHSV){
IplImage* imgThresh=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
IplImage* imgThresh2=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
IplImage* imgThresh3=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
cvInRangeS(imgHSV, cvScalar(170,160,60), cvScalar(180,256,256), imgThresh2);
cvInRangeS(imgHSV, cvScalar(0,160,60), cvScalar(22,256,256), imgThresh3);
cvOr(imgThresh2, imgThresh3, imgThresh);
cvInRangeS(imgHSV, cvScalar(75,160,60), cvScalar(130,256,256), imgThresh3);
cvOr(imgThresh, imgThresh3, imgThresh);
return imgThresh;
}

int main(){
CvCapture* capture =0;

capture = cvCaptureFromCAM(0);
if(!capture){
printf("Capture failure\n");
return -1;
}

IplImage * frame = 0;

cvNamedWindow("Video");
cvNamedWindow("Ball");//iterate through each frames of the video
while(true){

frame = cvQueryFrame(capture);
if(!frame) break;

frame=cvCloneImage(frame);
//cvSmooth(frame, frame, CV_GAUSSIAN,3,3); //smooth the original image using Gaussian kernel

//IplImage* imgHSV = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
//cvCvtColor(frame, imgHSV, CV_BGR2HSV); //Change the color format from BGR to HSV
//IplImage* imgThresh = GetThresholdedImage(imgHSV);
//IplImage* imgThresh=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
//cvCvtColor(imgHSV, imgThresh, CV_HSV2BGR);
//cvSmooth(imgThresh, imgThresh, CV_GAUSSIAN,3,3); //smooth the binary image using Gaussian kernel

//cvShowImage("Ball", imgThresh);

int sum = 150;

for(int i=0; i< frame->height; i++){
for(int j=0; j< frame->width; j++){
int blue = frame->imageData[frame->widthStep*i + frame->nChannels* j + 0];
int green = frame->imageData[frame->widthStep*i + frame->nChannels* j + 1];
int red = frame->imageData[frame->widthStep*i + frame->nChannels* j + 2];
//cout << red << " " << green << " " << blue << endl;
if ( red + 128 >= sum)
{
if (blue < 30)
{
if (green < 30)
{
frame->imageData[frame->widthStep*i + frame->nChannels* j + 0] = 255;
frame->imageData[frame->widthStep*i + frame->nChannels* j + 1] = 255;
frame->imageData[frame->widthStep*i + frame->nChannels* j + 2] = 255;
}
}

}

}
}
cvShowImage("Video", frame);if (sum > 1) { cout << "Detected"; }
else { cout << "Not Detected"; }

//Clean up used images
//cvReleaseImage(&imgHSV);
//cvReleaseImage(&imgThresh);
cvReleaseImage(&frame);

//Wait 50mS
int c = cvWaitKey(10);
//If 'ESC' is pressed, break the loop
if((char)c==27 ) break;
}

cvDestroyAllWindows() ;
cvReleaseCapture(&capture);

return 0;
}
0

хорошо, код Мэггика работает, за исключением некоторых незначительных изменений … Это обнаружит красные цвета.

#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>

using namespace std;

int main(){
CvCapture* capture =0;

capture = cvCaptureFromCAM(0);
if(!capture){
printf("Capture failure\n");
return -1;
}

IplImage * frame = 0;

cvNamedWindow("Video");

//iterate through each frames of the video
while(true){

frame = cvQueryFrame(capture);
if(!frame) break;

frame=cvCloneImage(frame);

int sum = 0;

for(int i=0; i< frame->height; i++){
for(int j=0; j< frame->width; j++){
int blue = frame->imageData[frame->widthStep*i + frame->nChannels* j + 0];
int green = frame->imageData[frame->widthStep*i + frame->nChannels* j + 1];
int red = frame->imageData[frame->widthStep*i + frame->nChannels* j + 2];
//cout << red << " " << green << " " << blue << endl;
if ( red + 128 >= 250)
{
if (blue < 50)
{
if (green < 50)
{
frame->imageData[frame->widthStep*i + frame->nChannels* j + 0] = 255;
frame->imageData[frame->widthStep*i + frame->nChannels* j + 1] = 255;
frame->imageData[frame->widthStep*i + frame->nChannels* j + 2] = 255;
sum = 1
}
}
}
}
}
cvShowImage("Video", frame);

if (sum > 0) { cout << "Detected"; }
else { cout << "Not Detected"; }

cvReleaseImage(&frame);

//Wait 50mS
int c = cvWaitKey(10);
//If 'ESC' is pressed, break the loop
if((char)c==27 ) break;
}

cvDestroyAllWindows() ;
cvReleaseCapture(&capture);

return 0;
}
0
По вопросам рекламы [email protected]