Gibt es eine Möglichkeit zu erkennen, ob ein Bild verschwommen ist?


Antworten:


133

Ja, so ist es. Berechnen Sie die schnelle Fourier-Transformation und analysieren Sie das Ergebnis. Die Fourier-Transformation zeigt an, welche Frequenzen im Bild vorhanden sind. Wenn nur wenige hohe Frequenzen vorhanden sind, ist das Bild verschwommen.

Es liegt an Ihnen, die Begriffe "niedrig" und "hoch" zu definieren.

Bearbeiten :

Wie in den Kommentaren angegeben, müssen Sie eine geeignete Metrik ausarbeiten , wenn Sie einen einzelnen Gleitkommawert wünschen, der die Unschärfe eines bestimmten Bildes darstellt.

Nikies Antwort liefert eine solche Metrik. Falten Sie das Bild mit einem Laplace-Kernel:

   1
1 -4  1
   1

Verwenden Sie eine robuste maximale Metrik für die Ausgabe, um eine Zahl zu erhalten, die Sie für die Schwellenwertbildung verwenden können. Vermeiden Sie es, die Bilder zu stark zu glätten, bevor Sie den Laplace-Wert berechnen, da Sie nur feststellen werden, dass ein geglättetes Bild tatsächlich verschwommen ist :-).


9
einziges problem das 'low' und 'high' sind auch szenenabhängig. +1
Kenny

4
Wenn Ihr Bild nicht zyklisch ist, haben Sie normalerweise scharfe Kanten an den Bildrändern, die zu sehr hohen Frequenzen führen
Niki

2
Normalerweise erweitern Sie Ihr Bild virtuell, um diesen Effekt zu vermeiden. Sie können auch kleine Fenster verwenden, um die lokale FFT zu berechnen.
Simon Bergot

6
Nur ein Punkt, der enorm wichtig ist, ist, dass Sie (zumindest grob) wissen müssen, wie hoch Ihr erwarteter vorunschärferer Bildinhalt (Frequenz) war. Dies ist wahr, da das Frequenzspektrum das des Originalbildes mal dem des Unschärfefilters sein wird. Wenn das Originalbild bereits überwiegend niedrige Frequenzen hatte, wie können Sie dann feststellen, ob es unscharf war?
Chris A.

1
Wenn Sie ein Foto eines leeren weißen Diagramms aufnehmen, können Sie nicht feststellen, ob das Bild verschwommen ist oder nicht. Ich denke, das OP will eine absolute Schärfemessung. Das vor verschwommene Bild ist möglicherweise überhaupt nicht vorhanden. Sie müssen ein wenig arbeiten, um eine korrekte Metrik zu erhalten, aber fft kann bei diesem Problem helfen. In dieser Perspektive ist Nickies Antwort besser als meine.
Simon Bergot

158

Eine andere sehr einfache Möglichkeit, die Schärfe eines Bildes abzuschätzen, besteht darin, einen Laplace-Filter (oder LoG-Filter) zu verwenden und einfach den Maximalwert auszuwählen. Die Verwendung eines robusten Maßes wie eines 99,9% -Quantils ist wahrscheinlich besser, wenn Sie Rauschen erwarten (dh den n-ten höchsten Kontrast anstelle des höchsten Kontrasts auswählen). Wenn Sie eine unterschiedliche Bildhelligkeit erwarten, sollten Sie auch einen Vorverarbeitungsschritt zur Normalisierung der Bildhelligkeit einschließen. Kontrast (zB Histogrammausgleich).

Ich habe Simons Vorschlag und diesen in Mathematica implementiert und an einigen Testbildern ausprobiert:

Testbilder

Der erste Test verwischt die Testbilder mit einem Gaußschen Filter mit variierender Kernelgröße, berechnet dann die FFT des unscharfen Bildes und berechnet den Durchschnitt der 90% höchsten Frequenzen:

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

Ergebnis in einem logarithmischen Diagramm:

fft Ergebnis

Die 5 Linien repräsentieren die 5 Testbilder, die X-Achse repräsentiert den Gaußschen Filterradius. Die Grafiken nehmen ab, daher ist die FFT ein gutes Maß für die Schärfe.

Dies ist der Code für den Schätzer für die "höchste LoG" -Unschärfe: Er wendet einfach einen LoG-Filter an und gibt das hellste Pixel im Filterergebnis zurück:

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

Ergebnis in einem logarithmischen Diagramm:

Laplace-Ergebnis

Die Streuung für die unscharfen Bilder ist hier etwas besser (2,5 gegenüber 3,3), hauptsächlich weil diese Methode nur den stärksten Kontrast im Bild verwendet, während die FFT im Wesentlichen ein Mittelwert über das gesamte Bild ist. Die Funktionen nehmen auch schneller ab, sodass es möglicherweise einfacher ist, einen "verschwommenen" Schwellenwert festzulegen.


1
Was ist, wenn ich nach dem Maß der lokalen Unschärfe bin? Ein Foto hat nämlich Bereiche, in denen es unscharf und scharf ist. Ich möchte eine Karte haben, die den Unschärfepegel pro Pixel schätzt.
Royi

4
@ Drake: Ich bin mir nicht sicher, ob das überhaupt möglich ist. Schauen Sie sich zum Beispiel das Lena-Bild an: Es gibt große Bereiche, in denen kein Kontrast vorhanden ist (z. B. Lenas Haut), obwohl der Bereich scharfgestellt ist. Ich kann mir keine Möglichkeit vorstellen, festzustellen, ob ein so glatter Bereich "verschwommen" ist, oder ihn von einem unscharfen Bereich zu unterscheiden. Sie sollten dies als separate Frage stellen (möglicherweise auf DSP.SE). Vielleicht hat jemand anderes bessere Ideen.
Niki

1
Ist es für Bewegungsunschärfe geeignet? oder nur für Unschärfe wie Gauß?
Mrgloom

@pparescasellas Möchten Sie Ihre Implementierungen teilen? Ich wäre neugierig, sie zu sehen.
Chappjc

@ JohnBoe Ich denke, Sie wollten
pparescasellas

79

Bei einigen Arbeiten mit einem Autofokus-Objektiv bin ich auf diese sehr nützlichen Algorithmen zur Erkennung des Bildfokus gestoßen . Es ist in MATLAB implementiert, aber die meisten Funktionen lassen sich mit filter2D recht einfach auf OpenCV portieren .

Es handelt sich im Grunde genommen um eine Umfrageimplementierung vieler Fokusmessalgorithmen. Wenn Sie die Originalarbeiten lesen möchten, finden Sie im Code Verweise auf die Autoren der Algorithmen. Das 2012 erschienene Papier von Pertuz et al. Die Analyse der Operatoren für Fokusmessungen auf Form aus Fokus (SFF) bietet eine hervorragende Übersicht über alle diese Messungen sowie über ihre Leistung (sowohl in Bezug auf Geschwindigkeit als auch Genauigkeit in Bezug auf SFF).

BEARBEITEN: MATLAB-Code für den Fall hinzugefügt, dass der Link stirbt.

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

Einige Beispiele für OpenCV-Versionen:

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

Keine Garantie dafür, ob diese Maßnahmen die beste Wahl für Ihr Problem sind oder nicht. Wenn Sie jedoch die mit diesen Maßnahmen verbundenen Dokumente aufspüren, erhalten Sie möglicherweise mehr Einblick. Ich hoffe, Sie finden den Code nützlich! Ich weiß, dass ich es getan habe.


Was wäre im Tenengrad-Algorithmus ein Nennwert für kSize?
Mans

@mans Ich verwende normalerweise 3, 5 oder 7, abhängig von der Auflösung des Bildes. Wenn Sie feststellen, dass Sie höher gehen müssen, sollten Sie sich das Downsampling des Bildes ansehen.
Mevatron

32

Aufbauend auf der Antwort von Nike. Es ist einfach, die auf Laplace basierende Methode mit opencv zu implementieren:

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

Gibt einen Kurzschluss zurück, der die maximal erkannte Schärfe angibt. Dies basiert auf meinen Tests an realen Proben und ist ein ziemlich guter Indikator dafür, ob eine Kamera scharfgestellt ist oder nicht. Es überrascht nicht, dass Normalwerte szenenabhängig sind, aber viel weniger als die FFT-Methode, die eine zu hohe Falsch-Positiv-Rate aufweisen muss, um in meiner Anwendung nützlich zu sein.


Was wäre der Schwellenwert, um zu sagen, dass ein Bild verschwommen ist? Ich habe es getestet. Aber es zeigt einige unterschiedliche Ergebnisse. Können Sie mir bitte dabei helfen, den Schwellenwert festzulegen?
2vision2

Habe auch deinen Vorschlag ausprobiert, aber die Zahlen, die ich bekomme, sind etwas zufällig. Wenn ich eine neue Frage in Bezug auf diese spezielle Implementierung stelle, möchten Sie einen Blick darauf werfen? \
Stpn

@stpn Der richtige Schwellenwert ist szenenabhängig. In meiner Anwendung (CCTV) verwende ich einen Standardschwellenwert von 300. Bei Kameras, bei denen dies zu niedrig ist, ändert jemand vom Support den konfigurierten Wert für diese bestimmte Kamera.
Yaur

warum ist "maxLap = -32767;" ?
Clement Prem

Wir suchen den höchsten Kontrast und da wir mit signierten Shorts arbeiten, ist -32767 der niedrigstmögliche Wert. Es ist 2,5 Jahre her, seit ich diesen Code geschrieben habe, aber IIRC hatte ich Probleme mit 16U.
Yaur

23

Ich habe eine ganz andere Lösung gefunden. Ich musste Video-Standbilder analysieren, um das schärfste in jedem (X) Bild zu finden. Auf diese Weise würde ich Bewegungsunschärfe und / oder unscharfe Bilder erkennen.

Am Ende habe ich die Canny Edge-Erkennung verwendet und mit fast jeder Art von Video SEHR SEHR gute Ergebnisse erzielt (mit Nikies Methode hatte ich Probleme mit digitalisierten VHS-Videos und starken Interlaced-Videos).

Ich habe die Leistung optimiert, indem ich für das Originalbild einen Bereich von Interesse (ROI) festgelegt habe.

Verwenden von 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

Danke Nikie für diesen tollen Laplace-Vorschlag. OpenCV-Dokumente haben mich in die gleiche Richtung gelenkt: mit Python, cv2 (opencv 2.4.10) und numpy ...

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

Ergebnis ist zwischen 0-255. Ich fand, dass alles, was über 200 ist, sehr scharf ist, und um 100 ist es merklich verschwommen. Das Maximum wird nie wirklich viel unter 20, selbst wenn es vollständig verschwommen ist.


3
Ich habe 255 für 3 meiner Fotos. Und für ein perfekt fokussiertes Foto habe ich 108 erhalten. Ich denke also, dass die Wirksamkeit der Methode von etwas abhängt.
WindRider

Einverstanden mit @WindWider. Ein Beispielbild, bei dem dies fehlschlägt, ist dieses Bild. Ich denke, der Grund dafür ist, dass der Kontrast des Bildes und die entsprechenden Intensitätsunterschiede zwischen den Pixeln groß sind, obwohl das Bild wackelig ist, wodurch die Laplace-Werte relativ groß sind. Bitte korrigieren Sie mich, wenn ich falsch liege.
Resham Wadhwa

@ReshamWadhwa cc WindRider - dito - irgendwelche Ideen, wie man das behebt?
jtlz2

@ ggez44 Dies ist meine bevorzugte Antwort - aber der Wert ist eine Funktion der Anzahl der Pixel im Bild. Wissen Sie, wie dies theoretisch skaliert? Ich könnte es als neue Frage stellen, wird aber wahrscheinlich abgeschossen. Vielen Dank!
jtlz2

10

Eine Methode, die ich derzeit verwende, misst die Streuung der Kanten im Bild. Suchen Sie nach diesem Papier:

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

Es ist normalerweise hinter einer Paywall, aber ich habe einige kostenlose Exemplare gesehen. Grundsätzlich lokalisieren sie vertikale Kanten in einem Bild und messen dann, wie breit diese Kanten sind. Die Mittelung der Breite ergibt das endgültige Ergebnis der Unschärfeschätzung für das Bild. Breitere Kanten entsprechen verschwommenen Bildern und umgekehrt.

Dieses Problem gehört zum Bereich der Schätzung der Bildqualität ohne Referenz . Wenn Sie in Google Scholar nachschlagen, erhalten Sie zahlreiche nützliche Referenzen.

BEARBEITEN

Hier ist eine grafische Darstellung der Unschärfeschätzungen, die für die 5 Bilder in Nikies Beitrag erhalten wurden. Höhere Werte entsprechen einer größeren Unschärfe. Ich habe einen 11x11-Gauß-Filter mit fester Größe verwendet und die Standardabweichung variiert (mit dem convertBefehl von imagemagick , um die unscharfen Bilder zu erhalten).

Geben Sie hier die Bildbeschreibung ein

Vergessen Sie beim Vergleichen von Bildern unterschiedlicher Größe nicht, die Bildbreite zu normalisieren, da größere Bilder breitere Kanten haben.

Schließlich besteht ein erhebliches Problem darin, zwischen künstlerischer Unschärfe und unerwünschter Unschärfe zu unterscheiden (verursacht durch Fokusfehler, Komprimierung, Relativbewegung des Motivs zur Kamera), aber das geht über einfache Ansätze wie diesen hinaus. Schauen Sie sich als Beispiel für künstlerische Unschärfe das Lenna-Bild an: Lennas Spiegelbild ist verschwommen, aber ihr Gesicht ist perfekt fokussiert. Dies trägt zu einer höheren Unschärfeschätzung für das Lenna-Bild bei.


5

Ich habe eine Lösung basierend auf dem Laplace-Filter aus diesem Beitrag ausprobiert . Es hat mir nicht geholfen. Also habe ich die Lösung aus diesem Beitrag ausprobiert und sie war gut für meinen Fall (ist aber langsam):

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

Weniger unscharfes Bild hat Maximum sum !

Sie können Geschwindigkeit und Genauigkeit auch einstellen, indem Sie den Schritt ändern, z

dieser Teil

for x in range(width - 1):

Sie können durch diesen ersetzen

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

4

Die obigen Antworten haben viele Dinge erläutert, aber ich denke, es ist nützlich, eine konzeptionelle Unterscheidung zu treffen.

Was ist, wenn Sie ein unscharfes Bild eines unscharfen Bildes perfekt fokussieren?

Das Problem der Unschärferkennung ist nur dann gut gestellt, wenn Sie eine Referenz haben . Wenn Sie beispielsweise ein Autofokus-System entwerfen müssen, vergleichen Sie eine Folge von Bildern, die mit unterschiedlichem Grad an Unschärfe oder Glättung aufgenommen wurden, und versuchen, den Punkt der minimalen Unschärfe innerhalb dieses Satzes zu finden. Mit anderen Worten, Sie müssen die verschiedenen Bilder mit einer der oben dargestellten Techniken verweisen (im Grunde genommen - mit verschiedenen möglichen Verfeinerungsstufen im Ansatz - nach dem einen Bild mit dem höchsten Hochfrequenzgehalt suchen).


2
Mit anderen Worten, es ist eine relative Vorstellung, es ist nur möglich zu erkennen, ob ein Bild mehr oder weniger unscharf ist als ein anderes ähnliches Bild. dh wenn es mehr oder weniger hochfrequenten Inhalt in seiner FFT hat. Sonderfall: Was ist, wenn das Bild benachbarte Pixel mit maximaler und minimaler Leuchtkraft hat? Zum Beispiel ein vollständig schwarzes Pixel neben einem vollständig weißen Pixel. In diesem Fall ist es ein perfekter Fokus, sonst würde es einen sanfteren Übergang von Schwarz zu Weiß geben. Perfekter Fokus in der Fotografie nicht wahrscheinlich, aber die Frage gibt nicht die Quelle des Bildes an (es könnte computergeneriert sein).
Ben

1

Matlab-Code von zwei Methoden, die in angesehenen Fachzeitschriften veröffentlicht wurden (IEEE Transactions on Image Processing), finden Sie hier: https://ivulab.asu.edu/software

Überprüfen Sie die CPBDM- und JNBM-Algorithmen. Wenn Sie den Code überprüfen, ist es nicht sehr schwer, ihn zu portieren, und er basiert übrigens auf der Marzialiano-Methode als Grundfunktion.


1

Ich implementierte es mit fft in matlab und überprüfe das Histogramm des fft-Berechnungsmittelwerts und des std, aber es kann auch eine Anpassungsfunktion durchgeführt werden

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

Das mache ich in Opencv, um die Fokusqualität in einer Region zu erkennen:

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];
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.