OpenCV中的本地归一化

7
我正在尝试在OpenCV中实现一种本地归一化算法,以减少图像中的照明差异。我找到了一个MATLAB函数,并在OpenCV中实现了它。然而,我得到的结果与MATLAB函数给出的结果不同。
这是我的代码:
Mat localNorm(Mat image, float sigma1, float sigma2)
{
    Mat floatGray, blurred1, blurred2, temp1, temp2, res;

    image.convertTo(floatGray, CV_32FC1);
    floatGray = floatGray/255.0;

    int blur1 = 2*ceil(-NormInv(0.05, 0, sigma1))+1;
    cv::GaussianBlur(floatGray, blurred1, cv::Size(blur1,blur1), sigma1);
    temp1 = floatGray-blurred1;

    cv::pow(temp1, 2.0, temp2);
    int blur2 = 2*ceil(-NormInv(0.05, 0, sigma2))+1;
    cv::GaussianBlur(temp2, blurred2, cv::Size(blur2,blur2), sigma2);
    cv::pow(blurred2, 0.5, temp2);

    floatGray = temp1/temp2;
    floatGray = 255.0*floatGray;
    floatGray.convertTo(res, CV_8UC1);

    return res;
}

NormInv 函数是由 Euan Dean 在 this post 中给出的 C++ 实现。

下面展示了我得到的结果和理论结果,对于相同的 sigma1sigma2 值(分别为 2.0 和 20.0)。

http://s9.postimage.org/3xfdf8f8f/Results.jpg

我已经尝试使用不同的值来设置sigma1和sigma2,但是它们似乎都不起作用。我还尝试在高斯函数中将blur1和blur2设置为0,但也无济于事。
任何帮助将不胜感激。先行致谢。
3个回答

11
你需要在将图像转换为CV_8UC1之前将其归一化到0到255之间。

谢谢您的回答,解决了我的问题。我改变了行floatGray = 255.0 * floatGray,并使用cv :: normalize(floatGray,res,0,255,NORM_MINMAX,CV_8UC1)代替,现在它可以工作了。我以为乘以255会使图像归一化,但我错了。谢谢。 - stfani

7
这是我的实现(我使用sigma1=2sigma2=20):
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;

int main(int argc, char** argv)
{
    Mat img, gray, float_gray, blur, num, den;

    // Load color image
    img = cv::imread("lena.png", 1);
    if( !img.data ) {
        return -1;
    }

    // convert to grayscale
    cv::cvtColor(img, gray, CV_BGR2GRAY);

    // convert to floating-point image
    gray.convertTo(float_gray, CV_32F, 1.0/255.0);

    // numerator = img - gauss_blur(img)
    cv::GaussianBlur(float_gray, blur, Size(0,0), 2, 2);
    num = float_gray - blur;

    // denominator = sqrt(gauss_blur(img^2))
    cv::GaussianBlur(num.mul(num), blur, Size(0,0), 20, 20);
    cv::pow(blur, 0.5, den);

    // output = numerator / denominator
    gray = num / den;

    // normalize output into [0,1]
    cv::normalize(gray, gray, 0.0, 1.0, NORM_MINMAX, -1);

    // Display
    namedWindow("demo", CV_WINDOW_AUTOSIZE );
    imshow("demo", gray);

    waitKey(0);

    return 0;
}

结果如预期:

规范化图像

请注意,您可以将内核大小指定为Size(0,0),它将从sigma值计算而来。


谢谢,这也非常有帮助。我一旦获得更高的声望就会给您的答案点赞。 - stfani

1
这是相同算法的Python实现:
import cv2
import numpy as np

img = cv2.imread('/home/anmol/Downloads/lena.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

float_gray = gray.astype(np.float32) / 255.0

blur = cv2.GaussianBlur(float_gray, (0, 0), sigmaX=2, sigmaY=2)
num = float_gray - blur

blur = cv2.GaussianBlur(num*num, (0, 0), sigmaX=20, sigmaY=20)
den = cv2.pow(blur, 0.5)

gray = num / den

gray = cv2.normalize(gray, dst=gray, alpha=0.0, beta=1.0, norm_type=cv2.NORM_MINMAX)

cv2.imwrite("./debug.png", gray * 255)

输出:

enter image description here


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