Görüntünün bulanık olup olmadığını tespit etmenin bir yolu var mı?


Yanıtlar:


133

Evet öyle. Hızlı Fourier Dönüşümünü hesaplayın ve sonucu analiz edin. Fourier dönüşümü, görüntüde hangi frekansların bulunduğunu gösterir. Düşük miktarda yüksek frekans varsa, görüntü bulanıklaşır.

'Düşük' ve 'yüksek' terimlerini tanımlamak size bağlıdır.

Düzenle :

Yorumlarda belirtildiği gibi, belirli bir görüntünün bulanıklığını temsil eden tek bir şamandıra istiyorsanız, uygun bir metrik oluşturmanız gerekir.

nikie'nin cevabı böyle bir metrik sağlıyor. Görüntüyü Laplacian çekirdeğiyle birleştirin:

   1
1 -4  1
   1

Eşikleme için kullanabileceğiniz bir sayı almak için çıktıda sağlam bir maksimum metrik kullanın. Laplacian'ı hesaplamadan önce görüntüleri çok fazla düzeltmekten kaçının, çünkü yalnızca düzgün bir görüntünün gerçekten bulanık olduğunu öğreneceksiniz :-).


9
sadece 'düşük' ve 'yüksek' problemleri de sahneye bağımlıdır. +1
kenny

4
Görüntünüz döngüsel olmadıkça, görüntünün kenarlarında çok yüksek frekanslara yol açan keskin kenarlara sahip olursunuz
Niki

2
genellikle bu efekti önlemek için görüntünüzü genişletirsiniz. yerel fft'yi hesaplamak için küçük pencereler de kullanabilirsiniz.
Simon Bergot

6
Son derece önemli olan tek nokta, ön bulanık görüntü (frekans) içeriğinizin ne olduğunu (en azından kabaca) bilmeniz gerektiğidir . Bu doğrudur, çünkü frekans spektrumu, bulanıklaştırma filtresinin orijinal görüntü süresiyle aynı olacaktır. Böylece, orijinal görüntü zaten düşük frekanslara sahipse, bulanık olup olmadığını nasıl anlarsınız?
Chris A.

1
Boş bir beyaz grafiğin fotoğrafını çekerseniz, görüntünün bulanık olup olmadığını söylemenin bir yolu yoktur. Bence OP bazı mutlak netlik ölçümü istiyor. önceden bulanıklaştırılmış görüntü hiç mevcut olmayabilir. Doğru bir metrikle gelmek için biraz çalışmalısınız, ancak fft bu soruna yardımcı olabilir. Bu açıdan nickie'nin cevabı benimkinden daha iyidir.
Simon Bergot

158

Bir görüntünün netliğini tahmin etmenin bir diğer çok basit yolu, bir Laplace (veya LoG) filtresi kullanmak ve sadece maksimum değeri seçmektir. Gürültü bekliyorsanız% 99,9 kantil gibi sağlam bir ölçü kullanmak muhtemelen daha iyidir (örneğin, en yüksek kontrast yerine N'inci en yüksek kontrastı seçmek.) Değişen görüntü parlaklığı bekliyorsanız, görüntü parlaklığını normalleştirmek / kontrast (örn. histogram eşitleme).

Simon'un önerisini ve bunu Mathematica'da uyguladım ve birkaç test görüntüsünde denedim:

Test görüntüleri

İlk test, değişen çekirdek boyutuna sahip bir Gauss filtresi kullanarak test görüntülerini bulanıklaştırır, daha sonra bulanık görüntünün FFT'sini hesaplar ve% 90 en yüksek frekansların ortalamasını alır:

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

Logaritmik bir arsa sonucu:

fft sonucu

5 çizgi 5 test görüntüsünü, X ekseni Gauss filtre yarıçapını temsil eder. Grafikler azalıyor, bu nedenle FFT keskinlik için iyi bir ölçüdür.

Bu, "en yüksek LoG" bulanıklığı tahmin edicisinin kodudur: Yalnızca bir LoG filtresi uygular ve filtre sonucundaki en parlak pikseli döndürür:

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

Logaritmik bir arsa sonucu:

laplace sonucu

Bulanık olmayan görüntüler için yayılma burada biraz daha iyidir (2.5'e karşı 3.3), çünkü bu yöntem sadece görüntüdeki en güçlü kontrastı kullanırken, FFT aslında tüm görüntü üzerinde bir ortalamadır. İşlevler de daha hızlı azalıyor, bu nedenle "bulanık" bir eşik ayarlamak daha kolay olabilir.


1
Yerel bulanıklığın ölçüsünün peşindeysem ne olur? Yani, Fotoğraf'ın bulanık ve keskin olduğu alanlar vardır. Piksel başına bulanıklık seviyesini tahmin eden bir harita istiyorum.
Royi

4
@Drazick: Bunun mümkün olup olmadığından emin değilim. Örneğin, Lena görüntüsüne bakın: Alan odaklanmış olmasına rağmen, kontrastın olmadığı geniş alanlar vardır (örneğin Lena'nın cildi). Böyle pürüzsüz bir alanın "bulanık" olup olmadığını anlamanın veya odak dışı alandan ayırt etmenin bir yolunu düşünemiyorum. Bunu ayrı bir soru olarak sormalısınız (belki DSP.SE'de). Belki başka birinin daha iyi fikirleri vardır.
Niki

1
Hareket bulanıklığı için uygun mu? veya sadece gauss gibi bulanıklık için mi?
mrgloom

@pparescasellas Uygulamalarınızı paylaşmak ister misiniz? Onları görmek isterdim.
chappjc

@JohnBoe Sanırım pparescasellas sormak istediniz
chappjc

80

Otomatik odaklama lensiyle yapılan bazı çalışmalar sırasında, görüntü odağını algılamak için bu çok kullanışlı algoritmalarla karşılaştım . MATLAB'da uygulanmıştır, ancak işlevlerin çoğu filter2D ile OpenCV'ye taşınması oldukça kolaydır .

Temelde birçok odak ölçüm algoritmasının bir anket uygulamasıdır. Orijinal makaleleri okumak istiyorsanız, kodda algoritma yazarlarına referanslar verilmiştir. Pertuz ve ark. Odak ölçü operatörlerinin odaktan şekil (SFF) analizi, tüm bu önlemlerin yanı sıra performanslarının (SFF'ye uygulanan hız ve doğruluk açısından) büyük bir incelemesini verir.

EDIT: Bağlantının ölmesi durumunda MATLAB kodu eklendi.

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
%******************************************************************

OpenCV sürümlerine birkaç örnek:

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

Bu önlemlerin probleminiz için en iyi seçim olup olmadığı konusunda hiçbir garanti yoktur, ancak bu önlemlerle ilişkili kağıtları takip ederseniz size daha fazla fikir verebilirler. Kodu faydalı bulacağınızı umuyoruz! Yaptığımı biliyorum.


tenengrad algoritmasında kSize için nominal bir değer ne olur?
adamın

@mans Görüntünün çözünürlüğüne bağlı olarak normalde 3, 5 veya 7 kullanıyorum. Bundan daha yükseğe çıkmanız gerektiğini fark ederseniz, görüntüyü aşağı örneklemeye bakmak isteyebilirsiniz.
mevatron

32

Nike'ın cevabından yola çıkarak. Laplacian tabanlı yöntemi opencv ile uygulamak basittir:

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

Gerçek dünya örnekleri üzerindeki testlerime dayanarak algılanan maksimum netliği gösteren kısa bir geri dönecek, bir kameranın odakta olup olmadığını gösteren oldukça iyi bir göstergedir. Şaşırtıcı olmayan bir şekilde, normal değerler sahneye bağımlıdır, ancak uygulamamda yararlı olması için yanlış pozitif oranı yüksek olan FFT yönteminden çok daha azdır.


Bir görüntünün bulanık olduğunu söylemek için harmanlık değeri ne olur? Test ettim. Ancak bazı farklı sonuçlar gösteriyor. Lütfen eşiği belirlemem için bana yardım eder misiniz?
2vision2

Ayrıca önerinizi denedim, ancak aldığım sayılar biraz rastgele. Bu özel uygulama ile ilgili yeni bir soruya başlarsam, bir göz atmak ister misiniz? \
Stpn

@stpn Doğru eşik sahneye bağlıdır. Uygulamamda (CCTV) 300 varsayılan eşiği kullanıyorum. Bunun için desteğin düşük olduğu kameralar söz konusu kamera için yapılandırılmış değeri değiştirecektir.
Yaur

neden "maxLap = -32767;" ?
Clement Prem

En yüksek kontrastı arıyoruz ve imzalı şortlarla çalıştığımız için -32767 mümkün olan en düşük değerdir. Bu kodu yazdığım 2.5 yıl oldu ama IIRC 16U kullanarak sorunları vardı.
Yaur

23

Tamamen farklı bir çözüm buldum. Her (X) karede en keskin olanı bulmak için video hareketsiz kareleri analiz etmem gerekiyordu. Bu şekilde, hareket bulanıklığını ve / veya odak dışı görüntüleri tespit ederdim.

Canny Edge algılama kullanarak sona erdi ve hemen hemen her tür video ile ÇOK ÇOK iyi sonuçlar aldım (nikie yöntemi ile, dijitalleştirilmiş VHS video ve ağır geçmeli videolar ile sorunları vardı).

Orijinal görüntüde bir ilgi alanı (ROI) ayarlayarak performansı optimize ettim.

EmguCV kullanma:

//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

Bu harika Laplace önerisi için teşekkürler nikie. OpenCV belgeleri bana aynı yöne işaret etti: python, cv2 (opencv 2.4.10) ve numpy kullanarak ...

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

sonuç 0-255 arasındadır. 200'ün üzerinde bir şeyin çok odaklandığını gördüm ve 100'e kadar belirgin bir şekilde bulanık. tamamen bulanık olsa bile max asla 20'nin altında olmaz.


3
3 fotoğrafım için 255 tane aldım. Ve mükemmel odaklanmış bir fotoğraf için 108 tane aldım. Bu yüzden, yöntemin etkinliği bir şeye bağlı olduğunu düşünüyorum.
WindRider

@WindWider ile aynı fikirde. Bunun başarısız olduğu örnek görüntü, bu görüntü olduğunu düşünüyorum, çünkü görüntü titrek olsa da, görüntünün kontrastı ve pikseller arasındaki karşılık gelen yoğunluk farkları büyüktür, bu nedenle Laplacian Değerleri nispeten büyüktür. Yanlışım varsa lütfen düzelt.
Resham Wadhwa

@ReshamWadhwa cc WindRider - ditto - bunu düzeltmek için herhangi bir fikir ??
jtlz2

@ ggez44 Bu benim tercih ettiğim cevap - ama değer görüntüdeki piksel sayısının bir fonksiyonudur. Bunun teorik olarak nasıl ölçeklendiğini biliyor musunuz? Bunu yeni bir soru olarak sorabilirim, ancak muhtemelen düşürülecek. Teşekkürler!
jtlz2

10

Şu anda kullandığım bir yol, görüntüdeki kenarların yayılmasını ölçer. Şu makaleye bakın:

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

Genellikle bir ödeme duvarının arkasında ama bazı ücretsiz kopyalar gördüm. Temel olarak, bir görüntüdeki dikey kenarları bulurlar ve daha sonra bu kenarların ne kadar geniş olduğunu ölçerler. Genişliğin ortalaması, görüntü için son bulanıklaştırma tahmini sonucunu verir. Daha geniş kenarlar bulanık görüntülere karşılık gelir ve bunun tersi de geçerlidir.

Bu sorun referanssız görüntü kalitesi tahmini alanına aittir . Google Akademik'te ararsanız, birçok yararlı referans alırsınız.

DÜZENLE

İşte nikie'nin gönderisindeki 5 resim için elde edilen bulanıklık tahminlerinin bir grafiği. Daha yüksek değerler daha fazla bulanıklığa karşılık gelir. Sabit boyutlu 11x11 Gauss filtresi kullandım ve standart sapmayı değiştirdim ( convertbulanık görüntüleri elde etmek için imagemagick komutunu kullanarak ).

resim açıklamasını buraya girin

Farklı boyutlardaki görüntüleri karşılaştırırsanız, daha büyük görüntüler daha geniş kenarlara sahip olacağından görüntü genişliğine göre normalleştirmeyi unutmayın.

Son olarak, önemli bir sorun sanatsal bulanıklığı ve istenmeyen bulanıklığı (odaklama özledim, sıkıştırma, öznenin kameraya göreli hareketinden kaynaklanan) ayırmaktır, ancak bu böyle basit yaklaşımların ötesindedir. Sanatsal bulanıklığın bir örneği için, Lenna görüntüsüne bir göz atın: Lenna'nın aynadaki yansıması bulanık, ancak yüzü mükemmel bir şekilde odaklanmıştır. Bu, Lenna görüntüsü için daha yüksek bir bulanıklık tahminine katkıda bulunur.


5

Ben gelen Laplace filtresine dayanarak çözüm çalıştı bu yazı. Bana yardımcı olmadı. Yani, gelen çözüm çalıştı bu yazı ve benim durum için iyiydi (ama yavaş):

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))

Daha az bulanık görüntü maksimum sumdeğere sahiptir!

Hızı ve doğruluğu, adımı değiştirerek de ayarlayabilirsiniz;

bu kısım

for x in range(width - 1):

bununla değiştirebilirsiniz

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

4

Yukarıdaki yanıtlar birçok şeyi açıkladı, ancak bence kavramsal bir ayrım yapmanın faydalı olduğunu düşünüyorum.

Ya bulanık bir görüntünün mükemmel odaklanmış bir fotoğrafını çekerseniz?

Bulanıklaştırma algılama sorunu yalnızca referansınız olduğunda iyi bir şekilde ortaya çıkar . Örneğin, bir otomatik odaklama sistemi tasarlamanız gerekiyorsa, farklı bulanıklaştırma veya yumuşatma dereceleriyle çekilen bir görüntü dizisini karşılaştırırsınız ve bu sette minimum bulanıklaştırma noktasını bulmaya çalışırsınız. Başka bir deyişle, yukarıda gösterilen tekniklerden birini kullanarak çeşitli görüntüleri çapraz referans almanız gerekir (temel olarak - yaklaşımda çeşitli olası iyileştirme seviyeleriyle - en yüksek yüksek frekans içeriğine sahip bir görüntü aranır).


2
Başka bir deyişle, bu göreceli bir kavramdır, ancak bir görüntünün benzer bir görüntüden daha fazla veya daha az bulanık olup olmadığını söylemek mümkündür. yani FFT'sinde az ya da çok yüksek frekans içeriğine sahipse. Özel durum: görüntünün maksimum ve minimum parlaklığa sahip bitişik pikselleri varsa ne olur? Örneğin, tamamen beyaz bir pikselin yanındaki tamamen siyah bir piksel. Bu durumda mükemmel bir odak, aksi takdirde siyahtan beyaza daha yumuşak bir geçiş olurdu. Fotoğrafta mükemmel odaklanma olası değildir, ancak soru görüntünün kaynağını belirtmez (bilgisayar tarafından oluşturulabilir).
Ben

1

Yüksek saygın dergilerde (Görüntü İşleme Üzerine IEEE İşlemleri) yayınlanan iki yöntemin Matlab koduna buradan ulaşabilirsiniz: https://ivulab.asu.edu/software

CPBDM ve JNBM algoritmalarını kontrol edin. Kodu kontrol ederseniz, taşınması çok zor değildir ve bu arada Marzialiano'nun temel özelliği olarak yöntemine dayanır.


1

i matlab içinde fft kullanın ve fft hesaplama ortalama ve std histogram kontrol edin ama aynı zamanda uyum fonksiyonu yapılabilir

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

Bir bölgede odak kalitesini tespit etmek için Opencv'de yaptığım şey bu:

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];
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.