Ich habe mich gefragt, ob es eine Möglichkeit gibt, durch Analysieren der Bilddaten festzustellen, ob ein Bild verschwommen ist oder nicht.
Ich habe mich gefragt, ob es eine Möglichkeit gibt, durch Analysieren der Bilddaten festzustellen, ob ein Bild verschwommen ist oder nicht.
Antworten:
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 :-).
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:
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:
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:
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.
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.
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.
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));
}
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.
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 convert
Befehl von imagemagick , um die unscharfen Bilder zu erhalten).
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.
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):
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).
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.
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(:));
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];