所以:我有这个OpenCV程序,它从相机捕获视频,并将其显示在两个窗口上。一个没有颜色检测;另一个突出显示某些特定的颜色(如红色)。
我需要的是一种方法来计算图像,在特定的时间,是否包含特定的颜色。现在,第一个窗口只是一个常规的视频输出。第二个窗口全是黑色,直到看到与我指定的颜色匹配的对象,这使得该对象在第二个窗口中显示为白色。
我想知道它何时被检测到,然后输出'detected'或'not detected'。
我该怎么做?我想我会迭代修改图像的宽度和高度,然后检查,但我不知道如何做到这一点。任何帮助感激-我一直试图找到这个问题的答案,现在没有运气。我检查了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 failuren");
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;
}
图像处理不是精确的科学,解决方案取决于输入数据…
- 如果您使用数字创建的图像,您可以在过滤图像上使用
cvCountNonZero
计算正像素 - 如果您的图像是真实世界的捕获,那么任何给定的图像都有可能在您的滤镜颜色中至少有一些像素。在局部滑动窗口中计算像素可能效果更好,但这肯定不是唯一的方法。例如,获取坐标(0,0)到(100,100)之间的区域,并计算非零的数量。如果超过某个数字,假设你得到的是正数。否则,继续进行重叠窗口(0,50)到(100,150)…
您可以循环遍历图像的行和颜色,如果红色值大于某个阈值,则可以将另一帧中的相应像素设置为白色。我也没有把它写在下面的代码中,但是你也可以设置绿色和蓝色的阈值。因为如果你要找的对象是红色的,那么它在绿色和蓝色记录中的位置就会比较低。
#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 failuren");
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;
}
除了一些小改动外,magic的代码工作正常…这将检测红色。
#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 failuren");
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;
}