OpenCV:在RGB图像上应用操作(拆分+合并)

4

如果这个问题太基础了,对不起,我还不熟悉OpenCV。

我想对一张RGB图像应用直方图均衡化。直方图均衡仅适用于单通道图像,因此我认为我必须将图像分成三个不同的通道,对每个通道应用直方图均衡,然后将它们合并在一起以形成输出均衡化图像。

所以我按照上述方法编写了程序,我真的相信它应该能工作:

#include <iostream>
#include <stdio.h>
#include <cv.h>
#include <highgui.h>

int main(int argc, char * argv[])
{
IplImage* img = cvLoadImage("/Users/Documents/red.jpg");  //Load image file
cvNamedWindow("Trans-in", CV_WINDOW_AUTOSIZE );     //Create input window
cvNamedWindow("Trans-out", CV_WINDOW_AUTOSIZE  );   //Create output window

cvShowImage("Trans-in", img );  //Show input image in input window

//Create space for outputs rgb and its separate channels, r, g and b
IplImage* img0 = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);    //rgb
IplImage* r = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);    //r
IplImage* g = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);    //g
IplImage* b = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);    //b

//cvZero(r);
//cvZero(g);
//cvZero(b);

cvSplit(img, b, g, r, NULL);       //OpenCV likes it in BGR format

cvEqualizeHist( img, r );    //equalise r
cvEqualizeHist( img, g );    //equalise g
cvEqualizeHist( img, b );    //equalise b


cvMerge(b, g, r, NULL, img0);  //merge all separate channels together to output image rgb

//cvReleaseImage(&r);
//cvReleaseImage(&g);
//cvReleaseImage(&b);

cvShowImage("Trans-out", img0); //Show output image in output window


cvWaitKey(0);
cvReleaseImage( &img);
cvReleaseImage( &img0);

cvDestroyWindow( "Trans-in");
cvDestroyWindow( "Trans-out");

return 0;
}

如果这些//注释有点烦人,我道歉,但这展示了我的“推理”吧。在我点击“运行”按钮之前,Xcode没有投诉。它基本上崩溃了(输入图像显示出来,但输出图像没有)。

底部还有一个错误消息:

OpenCV Error: Assertion failed (CV_ARE_SIZES_EQ(src, dst) && CV_ARE_TYPES_EQ(src, dst) && CV_MAT_TYPE(src->type) == CV_8UC1) in cvEqualizeHist, file /opt/local/var/macports/build/_Volumes_work_mports_dports_graphics_opencv/opencv/work/OpenCV-2.4.3/modules/imgproc/src/histogram.cpp, line 2414 terminate called throwing an exception

我完全不知道这意味着什么,下一步该怎么做。


1
您正在使用C++标签,但是OpenCV的C API。如果您是OpenCV的新手,您不应该学习C API,而应该使用C++ API!请参见http://docs.opencv.org/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.html#code - ypnos
哦,亲爱的,我会再次检查这个问题。我注意到C++ OpenCV倾向于使用“Mat”而不是“IplImage”,但迄今为止我的其他(但简单的)程序似乎都运行良好(我的编程语言是C++)。 - hettie
这是一个完全不同的话题。但你可以这样做:std::string str = "string"; const char *cstr = str.c_str(); - ypnos
@rotating_image...我知道通道分离均衡化是不正确的,正确的方法是对HSV/HSI/YUV等进行强度均衡化。我只是回答了实际问题,即为什么程序会导致断言失败。OP并没有问这种方法是否在理论上正确。 - sgarizvi
抱歉,我对OpenCV完全不熟悉,所以我只是按照官方OpenCV教材中的示例进行操作(尽管我还没有开始使用mat类型)。在书中的“直方图均衡化”部分中,它说对于RGB图像,您需要先分离通道,然后对每个通道应用HE。所以这就是我所做的。sgar91提供的代码有效,至少我得到了更高对比度的输出图像。虽然我无法绝对确认,因为我没有(也不知道如何)查看实际的直方图。@rotating_image...我无法确认您的方法是否有效,因为我没有测试过,但还是谢谢! - hettie
显示剩余3条评论
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
4
您在以下行中不正确地使用了cvEqualizeHist函数:
cvEqualizeHist( img, r );    //equalise r
cvEqualizeHist( img, g );    //equalise g
cvEqualizeHist( img, b );    //equalise b

img是一个三通道图像,而rgb是单通道图像。 cvEqualizeHist不能处理三通道图像。

你需要完成以下任务:

cvEqualizeHist( r, r );    //equalise r
cvEqualizeHist( g, g );    //equalise g
cvEqualizeHist( b, b );    //equalise b

等等,它还是不工作!程序仍然崩溃,但这次没有错误消息。 - hettie
在第 "cvShowImage("Trans-out", img0);" 行,有一个小消息显示为 "Thread : Breakpoint 1.1"。 - hettie
哦我的天啊,我不知道发生了什么事情,我刚刚再次运行了程序(我没有编辑任何其他内容),它就可以工作了!非常感谢!! - hettie
@sgar 如果我们想要给图像赋予自己选择的值,或者对它们的值进行条件限制,例如 cv::split(img, bgr); if bgr[0] > 127.0;,该怎么办? - AHF
@Ahmad... 要应用条件,请使用 cv::threshold 并选择 cv::THRESH_TRUNC 选项。或者,如果您只想将所有像素设置为相同的值,请使用 setTo,如下所示:bgr[0].setTo(value); - sgarizvi

2

如果要对RGB图像进行直方图均衡化...需要将其转换为HSV图像,然后对V平面进行均衡化...

  1. convert RGB to HSV
  2. split HSV into H,S and V
  3. equalize V
  4. merge H,S and V

    vector<Mat> hsv_planes;
    cvtColor(image,image,CV_BGR2HSV);
    split(image,hsv_planes);
    equalizeHist(hsv_planes[2],hsv_planes[2]);
    merge(hsv_planes,image);
    cvtColor(image,image,CV_HSV2BGR);
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,