Có cách nào để phát hiện nếu một hình ảnh bị mờ?


203

Tôi đã tự hỏi liệu có cách nào để xác định xem một hình ảnh có bị mờ hay không bằng cách phân tích dữ liệu hình ảnh.


7
Câu hỏi liên quan có một câu trả lời tốt, nhưng cũng có một câu hỏi liên quan nhiều hơn. stackoverflow.com/questions/5180327/
Mạnh

1
Nó cũng có câu trả lời tồi tệ hơn nhiều.
John Shedletsky

Câu trả lời:


133

Vâng, đúng vậy. Tính toán Biến đổi Fourier nhanh và phân tích kết quả. Biến đổi Fourier cho bạn biết tần số nào có trong hình ảnh. Nếu có một lượng tần số cao thấp, thì hình ảnh bị mờ.

Xác định các thuật ngữ 'thấp' và 'cao' là tùy thuộc vào bạn.

Chỉnh sửa :

Như đã nêu trong các ý kiến, nếu bạn muốn một hình nổi duy nhất thể hiện độ mờ của một hình ảnh nhất định, bạn phải tìm ra một số liệu phù hợp.

câu trả lời của nikie cung cấp một số liệu như vậy. Truyền hình ảnh với nhân Laplacian:

   1
1 -4  1
   1

Và sử dụng một số liệu tối đa mạnh mẽ trên đầu ra để có được một số mà bạn có thể sử dụng để ngưỡng. Cố gắng tránh làm mịn quá nhiều hình ảnh trước khi tính toán Laplacian, bởi vì bạn sẽ chỉ phát hiện ra rằng một hình ảnh được làm mịn thực sự bị mờ :-).


9
chỉ có vấn đề 'thấp' và 'cao' cũng phụ thuộc vào cảnh. +1
kenny

4
Trừ khi hình ảnh của bạn có chu kỳ, bạn thường sẽ có các cạnh sắc nét ở viền của hình ảnh dẫn đến tần số rất cao
Niki

2
bạn thường hầu như mở rộng hình ảnh của mình để tránh hiệu ứng này. bạn cũng có thể sử dụng các cửa sổ nhỏ để tính toán fft cục bộ.
Simon Bergot

6
Chỉ có một điểm cực kỳ quan trọng là bạn phải biết (ít nhất là đại khái ) nội dung hình ảnh (tần số) được làm mờ dự kiến ​​của bạn là gì . Điều này đúng vì phổ tần số sẽ là thời gian của ảnh gốc so với bộ lọc làm mờ. Do đó, nếu hình ảnh gốc đã có tần số thấp chủ yếu, làm thế nào bạn có thể biết liệu nó có bị mờ không?
Chris A.

1
Nếu bạn chụp ảnh biểu đồ màu trắng trống, bạn không có cách nào để biết hình ảnh có bị mờ hay không. Tôi nghĩ rằng OP muốn một số phép đo độ sắc nét tuyệt đối. hình ảnh bị mờ có thể không tồn tại. Bạn phải làm việc một chút để đi kèm với một số liệu chính xác, nhưng fft có thể giúp giải quyết vấn đề này. Trong viễn cảnh này, câu trả lời của nick tốt hơn của tôi.
Simon Bergot

158

Một cách rất đơn giản khác để ước tính độ sắc nét của hình ảnh là sử dụng bộ lọc Laplace (hoặc LoG) và chỉ cần chọn giá trị tối đa. Sử dụng một biện pháp mạnh như lượng tử 99,9% có lẽ tốt hơn nếu bạn mong đợi nhiễu (tức là chọn độ tương phản cao nhất Nth thay vì độ tương phản cao nhất.) Nếu bạn mong đợi độ sáng hình ảnh thay đổi, bạn cũng nên bao gồm một bước tiền xử lý để bình thường hóa độ sáng hình ảnh / độ tương phản (ví dụ cân bằng biểu đồ).

Tôi đã thực hiện đề xuất của Simon và đề xuất này trong Mathematica và đã thử nó trên một vài hình ảnh thử nghiệm:

hình ảnh thử nghiệm

Thử nghiệm đầu tiên làm mờ các hình ảnh thử nghiệm bằng bộ lọc Gaussian với kích thước hạt nhân khác nhau, sau đó tính toán FFT của hình ảnh bị mờ và lấy trung bình của tần số cao nhất 90%:

testFft[img_] := Table[
  (
   blurred = GaussianFilter[img, r];
   fft = Fourier[ImageData[blurred]];
   {w, h} = Dimensions[fft];
   windowSize = Round[w/2.1];
   Mean[Flatten[(Abs[
       fft[[w/2 - windowSize ;; w/2 + windowSize, 
         h/2 - windowSize ;; h/2 + windowSize]]])]]
   ), {r, 0, 10, 0.5}]

Kết quả trong một lôgarit:

kết quả fft

5 dòng đại diện cho 5 hình ảnh thử nghiệm, trục X đại diện cho bán kính bộ lọc Gaussian. Các biểu đồ đang giảm, vì vậy FFT là một thước đo tốt cho độ sắc nét.

Đây là mã cho công cụ ước tính độ mờ "LoG cao nhất": Nó chỉ đơn giản áp dụng bộ lọc LoG và trả về pixel sáng nhất trong kết quả bộ lọc:

testLaplacian[img_] := Table[
  (
   blurred = GaussianFilter[img, r];
   Max[Flatten[ImageData[LaplacianGaussianFilter[blurred, 1]]]];
   ), {r, 0, 10, 0.5}]

Kết quả trong một lôgarit:

kết quả laplace

Sự lan truyền cho các hình ảnh không bị mờ ở đây tốt hơn một chút (2,5 so với 3,3), chủ yếu là do phương pháp này chỉ sử dụng độ tương phản mạnh nhất trong ảnh, trong khi FFT về cơ bản là trung bình trên toàn bộ hình ảnh. Các chức năng cũng đang giảm nhanh hơn, do đó có thể dễ dàng hơn để đặt ngưỡng "mờ".


1
Điều gì xảy ra nếu tôi sau khi đo độ mờ cục bộ. Cụ thể, Ảnh có các khu vực bị mờ và nơi sắc nét. Tôi muốn có một bản đồ ước tính mức độ mờ trên mỗi pixel.
Royi

4
@Drazick: Tôi không chắc liệu điều đó có khả thi hay không. Ví dụ: nhìn vào hình ảnh Lena: Có những khu vực rộng lớn không có độ tương phản (ví dụ như làn da của Lena) mặc dù khu vực đó nằm trong tiêu điểm. Tôi không thể nghĩ ra cách nào để biết khu vực mịn như vậy có "mờ" hay phân biệt khu vực đó với khu vực không tập trung. Bạn nên hỏi điều này như một câu hỏi riêng biệt (có thể trên DSP.SE). Có lẽ ai đó có ý tưởng tốt hơn.
Niki

1
Liệu nó có phù hợp để làm mờ chuyển động? hoặc chỉ cho mờ như gaussian?
mrgloom

@pparescasellas Bạn có sẵn lòng chia sẻ việc triển khai của mình không. Tôi tò mò muốn xem chúng.
chappjc

@ John John Tôi nghĩ bạn muốn hỏi pparescasellas
chappjc

79

Trong một số công việc với ống kính lấy nét tự động, tôi đã bắt gặp bộ thuật toán rất hữu ích này để phát hiện tiêu cự hình ảnh . Nó được triển khai trong MATLAB, nhưng hầu hết các chức năng khá dễ dàng chuyển sang OpenCV với bộ lọc2D .

Về cơ bản, đây là một triển khai khảo sát của nhiều thuật toán đo trọng tâm. Nếu bạn muốn đọc các bài báo gốc, các tham chiếu đến các tác giả của các thuật toán được cung cấp trong mã. Bài báo năm 2012 của Pertuz, et al. Phân tích các toán tử đo trọng tâm cho hình dạng từ tiêu điểm (SFF) đưa ra đánh giá tuyệt vời về tất cả các biện pháp này cũng như hiệu suất của chúng (cả về tốc độ và độ chính xác khi áp dụng cho SFF).

EDIT: Đã thêm mã MATLAB trong trường hợp liên kết bị chết.

function FM = fmeasure(Image, Measure, ROI)
%This function measures the relative degree of focus of 
%an image. It may be invoked as:
%
%   FM = fmeasure(Image, Method, ROI)
%
%Where 
%   Image,  is a grayscale image and FM is the computed
%           focus value.
%   Method, is the focus measure algorithm as a string.
%           see 'operators.txt' for a list of focus 
%           measure methods. 
%   ROI,    Image ROI as a rectangle [xo yo width heigth].
%           if an empty argument is passed, the whole
%           image is processed.
%
%  Said Pertuz
%  Abr/2010


if ~isempty(ROI)
    Image = imcrop(Image, ROI);
end

WSize = 15; % Size of local window (only some operators)

switch upper(Measure)
    case 'ACMO' % Absolute Central Moment (Shirvaikar2004)
        if ~isinteger(Image), Image = im2uint8(Image);
        end
        FM = AcMomentum(Image);

    case 'BREN' % Brenner's (Santos97)
        [M N] = size(Image);
        DH = Image;
        DV = Image;
        DH(1:M-2,:) = diff(Image,2,1);
        DV(:,1:N-2) = diff(Image,2,2);
        FM = max(DH, DV);        
        FM = FM.^2;
        FM = mean2(FM);

    case 'CONT' % Image contrast (Nanda2001)
        ImContrast = inline('sum(abs(x(:)-x(5)))');
        FM = nlfilter(Image, [3 3], ImContrast);
        FM = mean2(FM);

    case 'CURV' % Image Curvature (Helmli2001)
        if ~isinteger(Image), Image = im2uint8(Image);
        end
        M1 = [-1 0 1;-1 0 1;-1 0 1];
        M2 = [1 0 1;1 0 1;1 0 1];
        P0 = imfilter(Image, M1, 'replicate', 'conv')/6;
        P1 = imfilter(Image, M1', 'replicate', 'conv')/6;
        P2 = 3*imfilter(Image, M2, 'replicate', 'conv')/10 ...
            -imfilter(Image, M2', 'replicate', 'conv')/5;
        P3 = -imfilter(Image, M2, 'replicate', 'conv')/5 ...
            +3*imfilter(Image, M2, 'replicate', 'conv')/10;
        FM = abs(P0) + abs(P1) + abs(P2) + abs(P3);
        FM = mean2(FM);

    case 'DCTE' % DCT energy ratio (Shen2006)
        FM = nlfilter(Image, [8 8], @DctRatio);
        FM = mean2(FM);

    case 'DCTR' % DCT reduced energy ratio (Lee2009)
        FM = nlfilter(Image, [8 8], @ReRatio);
        FM = mean2(FM);

    case 'GDER' % Gaussian derivative (Geusebroek2000)        
        N = floor(WSize/2);
        sig = N/2.5;
        [x,y] = meshgrid(-N:N, -N:N);
        G = exp(-(x.^2+y.^2)/(2*sig^2))/(2*pi*sig);
        Gx = -x.*G/(sig^2);Gx = Gx/sum(Gx(:));
        Gy = -y.*G/(sig^2);Gy = Gy/sum(Gy(:));
        Rx = imfilter(double(Image), Gx, 'conv', 'replicate');
        Ry = imfilter(double(Image), Gy, 'conv', 'replicate');
        FM = Rx.^2+Ry.^2;
        FM = mean2(FM);

    case 'GLVA' % Graylevel variance (Krotkov86)
        FM = std2(Image);

    case 'GLLV' %Graylevel local variance (Pech2000)        
        LVar = stdfilt(Image, ones(WSize,WSize)).^2;
        FM = std2(LVar)^2;

    case 'GLVN' % Normalized GLV (Santos97)
        FM = std2(Image)^2/mean2(Image);

    case 'GRAE' % Energy of gradient (Subbarao92a)
        Ix = Image;
        Iy = Image;
        Iy(1:end-1,:) = diff(Image, 1, 1);
        Ix(:,1:end-1) = diff(Image, 1, 2);
        FM = Ix.^2 + Iy.^2;
        FM = mean2(FM);

    case 'GRAT' % Thresholded gradient (Snatos97)
        Th = 0; %Threshold
        Ix = Image;
        Iy = Image;
        Iy(1:end-1,:) = diff(Image, 1, 1);
        Ix(:,1:end-1) = diff(Image, 1, 2);
        FM = max(abs(Ix), abs(Iy));
        FM(FM<Th)=0;
        FM = sum(FM(:))/sum(sum(FM~=0));

    case 'GRAS' % Squared gradient (Eskicioglu95)
        Ix = diff(Image, 1, 2);
        FM = Ix.^2;
        FM = mean2(FM);

    case 'HELM' %Helmli's mean method (Helmli2001)        
        MEANF = fspecial('average',[WSize WSize]);
        U = imfilter(Image, MEANF, 'replicate');
        R1 = U./Image;
        R1(Image==0)=1;
        index = (U>Image);
        FM = 1./R1;
        FM(index) = R1(index);
        FM = mean2(FM);

    case 'HISE' % Histogram entropy (Krotkov86)
        FM = entropy(Image);

    case 'HISR' % Histogram range (Firestone91)
        FM = max(Image(:))-min(Image(:));


    case 'LAPE' % Energy of laplacian (Subbarao92a)
        LAP = fspecial('laplacian');
        FM = imfilter(Image, LAP, 'replicate', 'conv');
        FM = mean2(FM.^2);

    case 'LAPM' % Modified Laplacian (Nayar89)
        M = [-1 2 -1];        
        Lx = imfilter(Image, M, 'replicate', 'conv');
        Ly = imfilter(Image, M', 'replicate', 'conv');
        FM = abs(Lx) + abs(Ly);
        FM = mean2(FM);

    case 'LAPV' % Variance of laplacian (Pech2000)
        LAP = fspecial('laplacian');
        ILAP = imfilter(Image, LAP, 'replicate', 'conv');
        FM = std2(ILAP)^2;

    case 'LAPD' % Diagonal laplacian (Thelen2009)
        M1 = [-1 2 -1];
        M2 = [0 0 -1;0 2 0;-1 0 0]/sqrt(2);
        M3 = [-1 0 0;0 2 0;0 0 -1]/sqrt(2);
        F1 = imfilter(Image, M1, 'replicate', 'conv');
        F2 = imfilter(Image, M2, 'replicate', 'conv');
        F3 = imfilter(Image, M3, 'replicate', 'conv');
        F4 = imfilter(Image, M1', 'replicate', 'conv');
        FM = abs(F1) + abs(F2) + abs(F3) + abs(F4);
        FM = mean2(FM);

    case 'SFIL' %Steerable filters (Minhas2009)
        % Angles = [0 45 90 135 180 225 270 315];
        N = floor(WSize/2);
        sig = N/2.5;
        [x,y] = meshgrid(-N:N, -N:N);
        G = exp(-(x.^2+y.^2)/(2*sig^2))/(2*pi*sig);
        Gx = -x.*G/(sig^2);Gx = Gx/sum(Gx(:));
        Gy = -y.*G/(sig^2);Gy = Gy/sum(Gy(:));
        R(:,:,1) = imfilter(double(Image), Gx, 'conv', 'replicate');
        R(:,:,2) = imfilter(double(Image), Gy, 'conv', 'replicate');
        R(:,:,3) = cosd(45)*R(:,:,1)+sind(45)*R(:,:,2);
        R(:,:,4) = cosd(135)*R(:,:,1)+sind(135)*R(:,:,2);
        R(:,:,5) = cosd(180)*R(:,:,1)+sind(180)*R(:,:,2);
        R(:,:,6) = cosd(225)*R(:,:,1)+sind(225)*R(:,:,2);
        R(:,:,7) = cosd(270)*R(:,:,1)+sind(270)*R(:,:,2);
        R(:,:,7) = cosd(315)*R(:,:,1)+sind(315)*R(:,:,2);
        FM = max(R,[],3);
        FM = mean2(FM);

    case 'SFRQ' % Spatial frequency (Eskicioglu95)
        Ix = Image;
        Iy = Image;
        Ix(:,1:end-1) = diff(Image, 1, 2);
        Iy(1:end-1,:) = diff(Image, 1, 1);
        FM = mean2(sqrt(double(Iy.^2+Ix.^2)));

    case 'TENG'% Tenengrad (Krotkov86)
        Sx = fspecial('sobel');
        Gx = imfilter(double(Image), Sx, 'replicate', 'conv');
        Gy = imfilter(double(Image), Sx', 'replicate', 'conv');
        FM = Gx.^2 + Gy.^2;
        FM = mean2(FM);

    case 'TENV' % Tenengrad variance (Pech2000)
        Sx = fspecial('sobel');
        Gx = imfilter(double(Image), Sx, 'replicate', 'conv');
        Gy = imfilter(double(Image), Sx', 'replicate', 'conv');
        G = Gx.^2 + Gy.^2;
        FM = std2(G)^2;

    case 'VOLA' % Vollath's correlation (Santos97)
        Image = double(Image);
        I1 = Image; I1(1:end-1,:) = Image(2:end,:);
        I2 = Image; I2(1:end-2,:) = Image(3:end,:);
        Image = Image.*(I1-I2);
        FM = mean2(Image);

    case 'WAVS' %Sum of Wavelet coeffs (Yang2003)
        [C,S] = wavedec2(Image, 1, 'db6');
        H = wrcoef2('h', C, S, 'db6', 1);   
        V = wrcoef2('v', C, S, 'db6', 1);   
        D = wrcoef2('d', C, S, 'db6', 1);   
        FM = abs(H) + abs(V) + abs(D);
        FM = mean2(FM);

    case 'WAVV' %Variance of  Wav...(Yang2003)
        [C,S] = wavedec2(Image, 1, 'db6');
        H = abs(wrcoef2('h', C, S, 'db6', 1));
        V = abs(wrcoef2('v', C, S, 'db6', 1));
        D = abs(wrcoef2('d', C, S, 'db6', 1));
        FM = std2(H)^2+std2(V)+std2(D);

    case 'WAVR'
        [C,S] = wavedec2(Image, 3, 'db6');
        H = abs(wrcoef2('h', C, S, 'db6', 1));   
        V = abs(wrcoef2('v', C, S, 'db6', 1));   
        D = abs(wrcoef2('d', C, S, 'db6', 1)); 
        A1 = abs(wrcoef2('a', C, S, 'db6', 1));
        A2 = abs(wrcoef2('a', C, S, 'db6', 2));
        A3 = abs(wrcoef2('a', C, S, 'db6', 3));
        A = A1 + A2 + A3;
        WH = H.^2 + V.^2 + D.^2;
        WH = mean2(WH);
        WL = mean2(A);
        FM = WH/WL;
    otherwise
        error('Unknown measure %s',upper(Measure))
end
 end
%************************************************************************
function fm = AcMomentum(Image)
[M N] = size(Image);
Hist = imhist(Image)/(M*N);
Hist = abs((0:255)-255*mean2(Image))'.*Hist;
fm = sum(Hist);
end

%******************************************************************
function fm = DctRatio(M)
MT = dct2(M).^2;
fm = (sum(MT(:))-MT(1,1))/MT(1,1);
end

%************************************************************************
function fm = ReRatio(M)
M = dct2(M);
fm = (M(1,2)^2+M(1,3)^2+M(2,1)^2+M(2,2)^2+M(3,1)^2)/(M(1,1)^2);
end
%******************************************************************

Một vài ví dụ về các phiên bản OpenCV:

// OpenCV port of 'LAPM' algorithm (Nayar89)
double modifiedLaplacian(const cv::Mat& src)
{
    cv::Mat M = (Mat_<double>(3, 1) << -1, 2, -1);
    cv::Mat G = cv::getGaussianKernel(3, -1, CV_64F);

    cv::Mat Lx;
    cv::sepFilter2D(src, Lx, CV_64F, M, G);

    cv::Mat Ly;
    cv::sepFilter2D(src, Ly, CV_64F, G, M);

    cv::Mat FM = cv::abs(Lx) + cv::abs(Ly);

    double focusMeasure = cv::mean(FM).val[0];
    return focusMeasure;
}

// OpenCV port of 'LAPV' algorithm (Pech2000)
double varianceOfLaplacian(const cv::Mat& src)
{
    cv::Mat lap;
    cv::Laplacian(src, lap, CV_64F);

    cv::Scalar mu, sigma;
    cv::meanStdDev(lap, mu, sigma);

    double focusMeasure = sigma.val[0]*sigma.val[0];
    return focusMeasure;
}

// OpenCV port of 'TENG' algorithm (Krotkov86)
double tenengrad(const cv::Mat& src, int ksize)
{
    cv::Mat Gx, Gy;
    cv::Sobel(src, Gx, CV_64F, 1, 0, ksize);
    cv::Sobel(src, Gy, CV_64F, 0, 1, ksize);

    cv::Mat FM = Gx.mul(Gx) + Gy.mul(Gy);

    double focusMeasure = cv::mean(FM).val[0];
    return focusMeasure;
}

// OpenCV port of 'GLVN' algorithm (Santos97)
double normalizedGraylevelVariance(const cv::Mat& src)
{
    cv::Scalar mu, sigma;
    cv::meanStdDev(src, mu, sigma);

    double focusMeasure = (sigma.val[0]*sigma.val[0]) / mu.val[0];
    return focusMeasure;
}

Không đảm bảo về việc các biện pháp này có phải là lựa chọn tốt nhất cho vấn đề của bạn hay không, nhưng nếu bạn theo dõi các giấy tờ liên quan đến các biện pháp này, chúng có thể giúp bạn hiểu rõ hơn. Hy vọng bạn tìm thấy mã hữu ích! Tôi biết tôi làm được.


trong thuật toán tenengrad, giá trị danh nghĩa của kSize sẽ là bao nhiêu?
mans

@mans Tôi thường sử dụng 3, 5 hoặc 7 tùy theo độ phân giải của hình ảnh. Nếu bạn thấy bạn cần phải tăng cao hơn thế, bạn có thể muốn xem xét việc lấy mẫu xuống hình ảnh.
mevatron

32

Xây dựng câu trả lời của Nike. Thật đơn giản để thực hiện phương pháp dựa trên laplacian với opencv:

short GetSharpness(char* data, unsigned int width, unsigned int height)
{
    // assumes that your image is already in planner yuv or 8 bit greyscale
    IplImage* in = cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,1);
    IplImage* out = cvCreateImage(cvSize(width,height),IPL_DEPTH_16S,1);
    memcpy(in->imageData,data,width*height);

    // aperture size of 1 corresponds to the correct matrix
    cvLaplace(in, out, 1);

    short maxLap = -32767;
    short* imgData = (short*)out->imageData;
    for(int i =0;i<(out->imageSize/2);i++)
    {
        if(imgData[i] > maxLap) maxLap = imgData[i];
    }

    cvReleaseImage(&in);
    cvReleaseImage(&out);
    return maxLap;
}

Sẽ trả về một khoảng ngắn cho biết độ sắc nét tối đa được phát hiện, dựa trên các thử nghiệm của tôi trên các mẫu trong thế giới thực, là một chỉ báo khá tốt về việc máy ảnh có nằm trong tiêu cự hay không. Không ngạc nhiên, giá trị bình thường là cảnh phụ thuộc nhưng nhiều ít hơn so với phương pháp FFT trong đó có đến cao của một tỷ lệ dương tính giả là hữu ích trong ứng dụng của tôi.


Điều gì sẽ là giá trị ngưỡng để nói một hình ảnh là blury? Tôi đã thử nó. Nhưng nó cho thấy một số kết quả khác nhau. Bạn có thể vui lòng giúp tôi trong việc này để thiết lập ngưỡng?
2vision2

Cũng đã thử đề xuất của bạn, nhưng những con số tôi nhận được là một chút ngẫu nhiên. Nếu tôi bắt đầu một câu hỏi mới liên quan đến việc triển khai cụ thể này, bạn có quan tâm để xem không? \
Stpn

@stpn Ngưỡng bên phải phụ thuộc vào cảnh. Trong ứng dụng của tôi (CCTV) Tôi đang sử dụng ngưỡng mặc định là 300. Đối với các máy ảnh có mức hỗ trợ thấp sẽ thay đổi giá trị được cấu hình cho máy ảnh cụ thể đó.
Yaur

tại sao là "maxLap = -32767;" ?
Clement Prem

Chúng tôi đang tìm kiếm độ tương phản cao nhất và vì chúng tôi đang làm việc với quần short có chữ ký -32767 là giá trị thấp nhất có thể. Đã 2,5 năm kể từ khi tôi viết mã đó nhưng IIRC tôi gặp vấn đề khi sử dụng 16U.
Yaur

23

Tôi đã đưa ra một giải pháp hoàn toàn khác. Tôi cần phân tích các khung hình video tĩnh để tìm khung hình sắc nét nhất trong mọi khung hình (X). Bằng cách này, tôi sẽ phát hiện mờ chuyển động và / hoặc ra khỏi hình ảnh lấy nét.

Tôi đã kết thúc bằng cách sử dụng phát hiện Canny Edge và tôi đã nhận được RẤT RẤT kết quả tốt với hầu hết mọi loại video (với phương pháp của nikie, tôi gặp vấn đề với video VHS được số hóa và video nặng xen kẽ).

Tôi đã tối ưu hóa hiệu suất bằng cách đặt vùng quan tâm (ROI) trên ảnh gốc.

Sử dụng EmguCV:

//Convert image using Canny
using (Image<Gray, byte> imgCanny = imgOrig.Canny(225, 175))
{
    //Count the number of pixel representing an edge
    int nCountCanny = imgCanny.CountNonzero()[0];

    //Compute a sharpness grade:
    //< 1.5 = blurred, in movement
    //de 1.5 à 6 = acceptable
    //> 6 =stable, sharp
    double dSharpness = (nCountCanny * 1000.0 / (imgCanny.Cols * imgCanny.Rows));
}

17

Cảm ơn nikie cho đề nghị Laplace tuyệt vời đó. Các tài liệu OpenCV đã chỉ cho tôi theo cùng một hướng: sử dụng python, cv2 (opencv 2.4.10) và numpy ...

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) numpy.max(cv2.convertScaleAbs(cv2.Laplacian(gray_image,3)))

kết quả là từ 0-255. Tôi thấy bất cứ thứ gì trên 200ish đều rất tập trung và đến năm 100, nó mờ đi rõ rệt. tối đa không bao giờ thực sự nhận được nhiều dưới 20 ngay cả khi nó hoàn toàn bị mờ.


3
Tôi đã nhận được 255 cho 3 bức ảnh của tôi. Và đối với một bức ảnh tập trung hoàn hảo tôi đã nhận được 108. Vì vậy, tôi nghĩ rằng hiệu quả của phương pháp phụ thuộc vào điều gì đó.
WindRider

Đồng ý với @WindWider. Hình ảnh mẫu không thành công là hình ảnh này Tôi nghĩ lý do là mặc dù hình ảnh bị rung, độ tương phản của hình ảnh và cường độ tương ứng giữa các pixel là lớn, do đó Giá trị Laplacian tương đối lớn. Xin hãy sửa tôi nếu tôi sai.
Resham Wadhwa

@ReshamWadhwa cc WindRider - ditto - có ý tưởng nào về cách khắc phục điều này không ??
jtlz2

@ ggez44 Đây là câu trả lời ưa thích của tôi - nhưng giá trị là hàm số lượng pixel trong ảnh. Bạn có biết làm thế nào quy mô này về mặt lý thuyết? Tôi có thể hỏi nó như một câu hỏi mới nhưng có khả năng bị bắn hạ. Cảm ơn!
jtlz2

10

Một cách mà tôi hiện đang sử dụng là đo độ lan rộng của các cạnh trong ảnh. Hãy tìm bài báo này:

@ARTICLE{Marziliano04perceptualblur,
    author = {Pina Marziliano and Frederic Dufaux and Stefan Winkler and Touradj Ebrahimi},
    title = {Perceptual blur and ringing metrics: Application to JPEG2000,” Signal Process},
    journal = {Image Commun},
    year = {2004},
    pages = {163--172} }

Nó thường đứng sau một tường thành nhưng tôi đã thấy một số bản sao miễn phí xung quanh. Về cơ bản, họ định vị các cạnh dọc trong một hình ảnh, và sau đó đo các cạnh đó rộng bao nhiêu. Tính trung bình chiều rộng cho kết quả ước tính mờ cuối cùng cho hình ảnh. Các cạnh rộng hơn tương ứng với hình ảnh mờ và ngược lại.

Vấn đề này thuộc về lĩnh vực ước tính chất lượng hình ảnh không tham chiếu . Nếu bạn tra cứu nó trên Google Scholar, bạn sẽ nhận được nhiều tài liệu tham khảo hữu ích.

BIÊN TẬP

Đây là một âm mưu của các ước tính mờ thu được cho 5 hình ảnh trong bài đăng của nikie. Giá trị cao hơn tương ứng với độ mờ lớn hơn. Tôi đã sử dụng bộ lọc Gaussian 11x11 kích thước cố định và thay đổi độ lệch chuẩn (sử dụng convertlệnh của fantemagick để thu được các hình ảnh mờ).

nhập mô tả hình ảnh ở đây

Nếu bạn so sánh hình ảnh có kích thước khác nhau, đừng quên bình thường hóa theo chiều rộng hình ảnh, vì hình ảnh lớn hơn sẽ có các cạnh rộng hơn.

Cuối cùng, một vấn đề quan trọng là phân biệt giữa mờ nghệ thuật và mờ không mong muốn (gây ra bởi lỗi lấy nét, nén, chuyển động tương đối của đối tượng với máy ảnh), nhưng đó là cách tiếp cận đơn giản như cách này. Để có một ví dụ về mờ nghệ thuật, hãy nhìn vào hình ảnh Lenna: Hình ảnh phản chiếu của Lenna trong gương bị mờ, nhưng khuôn mặt của cô ấy hoàn toàn tập trung. Điều này góp phần ước tính độ mờ cao hơn cho hình ảnh Lenna.


5

Tôi đã thử giải pháp dựa trên bộ lọc Laplacian từ bài đăng này . Nó không giúp tôi. Vì vậy, tôi đã thử giải pháp từ bài đăng này và nó tốt cho trường hợp của tôi (nhưng chậm):

import cv2

image = cv2.imread("test.jpeg")
height, width = image.shape[:2]
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

def px(x, y):
    return int(gray[y, x])

sum = 0
for x in range(width-1):
    for y in range(height):
        sum += abs(px(x, y) - px(x+1, y))

Hình ảnh mờ ít hơn có sumgiá trị tối đa !

Bạn cũng có thể điều chỉnh tốc độ và độ chính xác bằng cách thay đổi bước, ví dụ:

phần này

for x in range(width - 1):

bạn có thể thay thế bằng cái này

for x in range(0, width - 1, 10):

4

Câu trả lời ở trên đã làm sáng tỏ nhiều điều, nhưng tôi nghĩ nó rất hữu ích để tạo ra sự khác biệt về khái niệm.

Điều gì nếu bạn chụp một bức ảnh hoàn toàn tập trung vào một hình ảnh mờ?

Vấn đề phát hiện mờ chỉ được đặt ra khi bạn có một tài liệu tham khảo . Nếu bạn cần thiết kế, ví dụ: hệ thống lấy nét tự động, bạn so sánh một chuỗi hình ảnh được chụp với các mức độ làm mờ hoặc làm mịn khác nhau và bạn cố gắng tìm điểm mờ tối thiểu trong bộ này. Nói cách khác, bạn cần tham chiếu chéo các hình ảnh khác nhau bằng một trong những kỹ thuật được minh họa ở trên (về cơ bản - với nhiều mức độ tinh chỉnh khác nhau trong cách tiếp cận - tìm kiếm một hình ảnh có nội dung tần số cao nhất).


2
Nói cách khác, đó là một khái niệm tương đối, chỉ có thể biết liệu một hình ảnh bị mờ nhiều hay ít hơn một hình ảnh tương tự khác. tức là nếu nó có nhiều hay ít nội dung tần số cao trong FFT của nó. Trường hợp cụ thể: nếu hình ảnh có các pixel liền kề với độ sáng tối đa và tối thiểu thì sao? Ví dụ, một pixel hoàn toàn đen bên cạnh một pixel hoàn toàn trắng. Trong trường hợp này, đó là một tiêu điểm hoàn hảo, nếu không sẽ có sự chuyển đổi mượt mà hơn từ đen sang trắng. Lấy nét hoàn hảo không có khả năng trong nhiếp ảnh, nhưng câu hỏi không chỉ định nguồn của hình ảnh (nó có thể là do máy tính tạo ra).
Ben

1

Mã Matlab của hai phương pháp đã được xuất bản trên các tạp chí được đánh giá cao (Giao dịch của IEEE về Xử lý hình ảnh) có sẵn tại đây: https://ivulab.asu.edu/software

kiểm tra các thuật toán CPBDM và JNBM. Nếu bạn kiểm tra mã, sẽ không khó để chuyển và tình cờ nó dựa trên phương pháp của Marzialiano như là tính năng cơ bản.


1

tôi đã thực hiện nó sử dụng fft trong matlab và kiểm tra biểu đồ của trung bình tính toán fft và std nhưng cũng có thể thực hiện chức năng phù hợp

fa =  abs(fftshift(fft(sharp_img)));
fb = abs(fftshift(fft(blured_img)));

f1=20*log10(0.001+fa);
f2=20*log10(0.001+fb);

figure,imagesc(f1);title('org')
figure,imagesc(f2);title('blur')

figure,hist(f1(:),100);title('org')
figure,hist(f2(:),100);title('blur')

mf1=mean(f1(:));
mf2=mean(f2(:));

mfd1=median(f1(:));
mfd2=median(f2(:));

sf1=std(f1(:));
sf2=std(f2(:));

1

Đó là những gì tôi làm trong Opencv để phát hiện chất lượng tập trung trong một khu vực:

Mat grad;
int scale = 1;
int delta = 0;
int ddepth = CV_8U;
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
/// Gradient X
Sobel(matFromSensor, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT);
/// Gradient Y
Sobel(matFromSensor, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
convertScaleAbs(grad_y, abs_grad_y);
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
cv::Scalar mu, sigma;
cv::meanStdDev(grad, /* mean */ mu, /*stdev*/ sigma);
focusMeasure = mu.val[0] * mu.val[0];
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.