2013-02-14 44 views
5

Tôi đang cố gắng triển khai OpenCV một thuật toán chuẩn hóa cục bộ để giảm sự khác biệt của ánh sáng trong hình ảnh. Tôi đã tìm thấy một MATLAB function và tôi đã triển khai nó trong OpenCV. Tuy nhiên, kết quả mà tôi nhận được khác với kết quả được đưa ra bởi hàm MATLAB.Chuẩn hóa cục bộ trong OpenCV

Đây là mã của tôi:

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; 
} 

Chức năng NormInv là ++ thực hiện C do Euan Dean trong this post.

Sau đây cho thấy kết quả mà tôi nhận được và kết quả lý thuyết, đối với cùng một giá trị của sigma1sigma2 (2,0 và 20,0, tương ứng)

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

Tôi đã cố gắng sử dụng các giá trị khác nhau cho sigma1sigma2, nhưng không ai trong số họ có vẻ hoạt động. Tôi cũng đã thử làm blur1=0blur2=0 trong hàm Gaussian nhưng nó cũng không hoạt động.

Mọi trợ giúp sẽ được đánh giá cao. Cảm ơn trước.

Trả lời

9

bạn cần phải chuẩn hóa hình ảnh từ 0 đến 255 trước khi chuyển đổi nó để CV_8UC1

+0

Cảm ơn bạn đã trả lời của bạn, đó là giải quyết vấn đề của tôi. Tôi thay đổi dòng floatGray = 255.0 * floatGray và sử dụng cv :: normalize (floatGray, res, 0, 255, NORM_MINMAX, CV_8UC1) thay vào đó và bây giờ nó hoạt động. Tôi nghĩ rằng nhân với 255 sẽ bình thường hóa hình ảnh, nhưng tôi đã sai. Cảm ơn. – stfani

7

Đây được thực hiện của tôi (Tôi đang sử dụng sigma1=2, sigma2=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; 
} 

Kết quả như mong đợi:

normalized_image

Lưu ý rằng bạn có thể chỉ định kích thước hạt nhân là Size(0,0) và nó sẽ được tính toán từ các giá trị sigma.

+0

Cảm ơn bạn, điều này cũng rất hữu ích. Tôi sẽ bình chọn câu trả lời của bạn ngay sau khi tôi nhận được danh tiếng cao hơn. – stfani

0

này là việc thực hiện Python của algo cùng trên:

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) 

outout:

enter image description here

Các vấn đề liên quan