在OpenCV C++中检测非均匀照明下的物体

4
我正在使用OpenCV C++在视频/实时流/图像中执行特征检测。由于不同部分的光照条件不同,将RGB图像转换为二进制图像时会忽略一些部分。
视频中特定部分的照明条件也会随着时间而改变。我尝试了“直方图均衡化”函数,但没有帮助。
我在以下链接中找到了MATLAB的解决方案:

http://in.mathworks.com/help/images/examples/correcting-nonuniform-illumination.html

然而,上述链接中使用的大多数函数在OpenCV中不可用。

你能否建议将这段MATLAB代码转换为OpenCV C++的替代方案?


以上链接中使用的大多数函数在OpenCV中都可用。 - Miki
是的,请尝试使用cv::morphologyEx。 - Yang Kui
2个回答

3

OpenCV框架中提供了自适应阈值的范例:http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold

函数原型如下:

void adaptiveThreshold(InputArray src, OutputArray dst, 
                      double maxValue, int adaptiveMethod, 
                      int thresholdType, int blockSize, double C);

前两个参数分别是输入图像和保存输出阈值图像的位置。maxValue 是通过条件判断后赋值给输出像素的阈值,adaptiveMethod 是自适应阈值化使用的方法,thresholdType 是要执行的阈值化类型(稍后会讲到),blockSize 是要检查的窗口的大小(稍后会讲到),C 是从每个窗口中减去的常数。我从未真正需要使用它,通常将其设置为0。 adaptiveThreshold 的默认方法是分析 blockSize x blockSize 窗口并计算该窗口内的平均强度减去 C。如果此窗口的中心在平均强度之上,则将输出位置的相应位置设置为 maxValue,否则同一位置将设置为 0。这应该解决了非均匀照明问题,而不是对整个图像应用全局阈值,而是在本地像素邻域上进行阈值化。
您可以阅读其他参数方法的文档,但是为了入门,您可以像这样做:
// Include libraries
#include <cv.h>
#include <highgui.h>

// For convenience
using namespace cv;

// Example function to adaptive threshold an image
void threshold() 
{
   // Load in an image - Change "image.jpg" to whatever your image is called
   Mat image;
   image = imread("image.jpg", 1);

   // Convert image to grayscale and show the image
   // Wait for user key before continuing
   Mat gray_image;
   cvtColor(image, gray_image, CV_BGR2GRAY);

   namedWindow("Gray image", CV_WINDOW_AUTOSIZE);
   imshow("Gray image", gray_image);   
   waitKey(0);

   // Adaptive threshold the image
   int maxValue = 255;
   int blockSize = 25;
   int C = 0;
   adaptiveThreshold(gray_image, gray_image, maxValue, 
                     CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 
                     blockSize, C);

   // Show the thresholded image
   // Wait for user key before continuing
   namedWindow("Thresholded image", CV_WINDOW_AUTOSIZE);
   imshow("Thresholded image", gray_image);
   waitKey(0);
}

// Main function - Run the threshold function
int main( int argc, const char** argv ) 
{
    threshold();
}

谢谢你的回复。 - Siyad M

1

adaptiveThreshold 应该是您的首选。

但是在这里,我报告了从Matlab到OpenCV的“翻译”,因此您可以轻松地将代码移植。正如您所看到的,大多数函数在Matlab和OpenCV中都可用。

#include <opencv2\opencv.hpp>
using namespace cv;

int main()
{   
    // Step 1: Read Image
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    // Step 2: Use Morphological Opening to Estimate the Background
    Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(15,15));
    Mat1b background;
    morphologyEx(img, background, MORPH_OPEN, kernel);

    // Step 3: Subtract the Background Image from the Original Image
    Mat1b img2;
    absdiff(img, background, img2);

    // Step 4: Increase the Image Contrast
    // Don't needed it here, the equivalent would be  cv::equalizeHist

    // Step 5(1): Threshold the Image
    Mat1b bw;
    threshold(img2, bw, 50, 255, THRESH_BINARY);

    // Step 6: Identify Objects in the Image
    vector<vector<Point>> contours;
    findContours(bw.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);


    for(int i=0; i<contours.size(); ++i)
    {
        // Step 5(2): bwareaopen
        if(contours[i].size() > 50)
        {
            // Step 7: Examine One Object
            Mat1b object(bw.size(), uchar(0));
            drawContours(object, contours, i, Scalar(255), CV_FILLED);

            imshow("Single Object", object);
            waitKey();
        }
    }

    return 0;
}

非常感谢您的帮助。我得到了我所需要的精确结果。再次感谢。 - Siyad M

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