Markus Trost
Markus Trost

Reputation: 21

OpenCV C++: Inconsistent Canny Edge Detection under varying lighting – How to improve preprocessing?

I'm working on an object detection project in C++ using OpenCV. Specifically, I capture an image (e.g., coins on a background) and then try to detect them via Canny edge detection and contour filtering. However, I struggle with getting consistent results under different lighting conditions. I have tried:

This is an example: Original: Original

After preprocessing: After preprocessing:

After Canny: After Canny

I use the following functions to prepare the image and detect edges. I've tried to build an “all-in-one” pipeline that includes sharpening, brightness/contrast adjustments, blur, either auto or manual Canny, optional dilation, and a final morphological operation.

Even though I can tune the parameters for one scenario, results often vary significantly when lighting changes slightly or the objects move. Sometimes edges look fine, other times they're broken or noisy.

A shortened version of my function:

void ObjectFinder::applyEdgeFilter(const cv::Mat& input, cv::Mat& preCanny, cv::Mat& edgeImage) const {
    cv::Mat gray;
    cv::cvtColor(input, gray, cv::COLOR_BGR2GRAY);
    cv::equalizeHist(gray, gray);

    cv::Mat sharpened;
    if (m_sharpenMode == 1) {
        cv::Mat blurredForSharpen;
        cv::GaussianBlur(gray, blurredForSharpen, cv::Size(0, 0), 3);
        double factor = (m_sharpenStrength / 100.0) - 1.0;
        cv::addWeighted(gray, 1 + factor, blurredForSharpen, -factor, 0, sharpened);
    } else if (m_sharpenMode == 2) {
        cv::medianBlur(gray, sharpened, 3);
    } else {
        sharpened = gray.clone();
    }

    double alpha = m_contrastValue / 100.0;
    int beta = m_brightnessValue - 100;
    cv::Mat brightContrastAdjusted;
    sharpened.convertTo(brightContrastAdjusted, -1, alpha, beta);

    double sigmaBlur = (m_blurSigmaValue == 0) ? 0.1 : m_blurSigmaValue / 10.0;
    cv::GaussianBlur(brightContrastAdjusted, preCanny, cv::Size(0, 0), sigmaBlur, sigmaBlur);

    if (m_autoCannyMode == 1) {
        double med = computeMedian(preCanny);
        double sigmaAuto = m_sigmaValue / 100.0;
        int lower = std::max(0, int((1.0 - sigmaAuto) * med));
        int upper = std::min(255, int((1.0 + sigmaAuto) * med));
        cv::Canny(preCanny, edgeImage, lower, upper);
    } else {
        cv::Canny(preCanny, edgeImage, m_lowThreshold, m_highThreshold);
    }

    if (m_showDilation == 1) {
        cv::dilate(edgeImage, edgeImage, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)));
    }

    cv::Mat morphKernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
    cv::morphologyEx(edgeImage, edgeImage, cv::MORPH_CLOSE, morphKernel);
}

Questions

Varying brightness, lamps, and backgrounds Manual vs. auto Canny thresholds Different morphological operations Different sharpening/blur filters (Gaussian, Median, Bilateral) Adjusting parameters on the fly with trackbars Despite these attempts, edges sometimes look great and other times are too noisy or broken.

Upvotes: 2

Views: 39

Answers (0)

Related Questions