ฉันสงสัยว่ามีวิธีการตรวจสอบว่าภาพพร่ามัวหรือไม่โดยการวิเคราะห์ข้อมูลภาพ
ฉันสงสัยว่ามีวิธีการตรวจสอบว่าภาพพร่ามัวหรือไม่โดยการวิเคราะห์ข้อมูลภาพ
คำตอบ:
ใช่แล้ว. คำนวณการแปลงฟูริเยร์อย่างรวดเร็วและวิเคราะห์ผลลัพธ์ การแปลงฟูริเยร์จะบอกคุณว่ามีความถี่ใดบ้างในภาพ หากมีความถี่สูงในระดับต่ำภาพจะเบลอ
การกำหนดคำว่า 'ต่ำ' และ 'สูง' ขึ้นอยู่กับคุณ
แก้ไข :
ดังที่ระบุไว้ในความคิดเห็นหากคุณต้องการให้โฟลตหนึ่งอันแสดงถึงความพร่ามัวของภาพที่ระบุคุณต้องคำนวณเมตริกที่เหมาะสม
คำตอบของ nikieให้เมตริกเช่นนั้น สร้างภาพที่น่าเชื่อถือด้วยเคอร์เนล Laplacian:
1
1 -4 1
1
และใช้ตัวชี้วัดสูงสุดที่แข็งแกร่งในผลลัพธ์เพื่อรับตัวเลขที่คุณสามารถใช้สำหรับการกำหนดเกณฑ์ขั้นต่ำ พยายามหลีกเลี่ยงการปรับภาพให้เรียบเกินไปก่อนที่จะคำนวณ Laplacian เพราะคุณจะพบว่าภาพที่ราบเรียบนั้นพร่ามัวจริง ๆ :-)
อีกวิธีที่ง่ายมากในการประมาณความคมชัดของภาพคือการใช้ฟิลเตอร์ Laplace (หรือ LoG) และเลือกค่าสูงสุด การใช้การวัดที่แข็งแกร่งเช่นควอไทล์ 99.9% น่าจะดีกว่าถ้าคุณคาดหวังว่าจะเกิดจุดรบกวน (เช่นการเลือกคอนทราสต์สูงสุด Nth แทนที่จะเป็นคอนทราสต์สูงสุด) หากคุณคาดหวังความสว่างของภาพที่แตกต่างกัน ความคมชัด (เช่นการทำให้เท่าเทียมกันฮิสโตแกรม)
ฉันได้ใช้คำแนะนำของ Simon และอันนี้ใน Mathematica แล้วลองทดสอบในภาพทดสอบสองสามภาพ:
การทดสอบครั้งแรกทำให้ภาพทดสอบเบลอโดยใช้ตัวกรอง Gaussian ที่มีขนาดเคอร์เนลที่แตกต่างกันจากนั้นคำนวณค่า FFT ของภาพเบลอและใช้ความถี่สูงสุด 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}]
ส่งผลให้พล็อตลอการิทึม:
5 เส้นแสดงถึงภาพทดสอบ 5 แกน X แสดงถึงรัศมีตัวกรองเกาส์เซียน กราฟลดลงดังนั้น FFT จึงเป็นเครื่องวัดที่ดีสำหรับความคมชัด
นี่คือรหัสสำหรับตัวประมาณค่าความพร่ามัว "สูงสุด LoG": มันใช้ตัวกรอง LoG และส่งคืนพิกเซลที่สว่างที่สุดในผลลัพธ์ตัวกรอง:
testLaplacian[img_] := Table[
(
blurred = GaussianFilter[img, r];
Max[Flatten[ImageData[LaplacianGaussianFilter[blurred, 1]]]];
), {r, 0, 10, 0.5}]
ส่งผลให้พล็อตลอการิทึม:
การแพร่กระจายของภาพที่ไม่เบลอดีกว่าเล็กน้อยที่นี่ (2.5 vs 3.3) ส่วนใหญ่เป็นเพราะวิธีนี้ใช้ความเปรียบต่างที่รุนแรงที่สุดในภาพในขณะที่ FFT นั้นมีความหมายโดยรวมมากกว่าภาพทั้งหมด ฟังก์ชั่นยังลดลงเร็วขึ้นด้วยดังนั้นจึงอาจง่ายกว่าในการตั้งค่าเกณฑ์ "เบลอ"
ในระหว่างการทำงานบางอย่างกับเลนส์ออโต้โฟกัสผมมาในชุดนี้มีประโยชน์มากของอัลกอริทึมสำหรับการตรวจจับโฟกัสภาพ ก็ดำเนินการใน MATLAB แต่ส่วนมากของฟังก์ชั่นที่ค่อนข้างง่ายที่จะพอร์ตไป OpenCV กับfilter2D
โดยพื้นฐานแล้วเป็นการสำรวจโดยใช้อัลกอริทึมการวัดโฟกัส หากคุณต้องการอ่านเอกสารต้นฉบับการอ้างอิงถึงผู้แต่งอัลกอริทึมนั้นมีอยู่ในรหัส กระดาษ 2012 โดย Pertuz และคณะ การวิเคราะห์ผู้ประกอบการวัดโฟกัสสำหรับรูปร่างจากโฟกัส (SFF) ให้การตรวจสอบที่ยอดเยี่ยมของมาตรการเหล่านี้รวมถึงประสิทธิภาพของพวกเขา (ทั้งในแง่ของความเร็วและความแม่นยำที่ใช้กับ SFF)
แก้ไข: เพิ่มรหัส MATLAB ในกรณีที่ลิงก์เสีย
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:
// 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;
}
ไม่มีการรับประกันว่ามาตรการเหล่านี้จะเป็นตัวเลือกที่ดีที่สุดสำหรับปัญหาของคุณหรือไม่ แต่ถ้าคุณติดตามเอกสารที่เกี่ยวข้องกับมาตรการเหล่านี้พวกเขาอาจให้ข้อมูลเชิงลึกมากขึ้น หวังว่าคุณจะพบโค้ดที่มีประโยชน์! ฉันรู้ว่าฉันทำ
ตัดคำตอบของ Nike ออก มันตรงไปตรงมาที่จะใช้วิธีการตาม laplacian กับ 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;
}
จะคืนค่าสั้น ๆ เพื่อระบุความคมชัดสูงสุดที่ตรวจพบซึ่งจากการทดสอบของฉันสำหรับตัวอย่างจริงเป็นตัวบ่งชี้ที่ดีว่ากล้องอยู่ในโฟกัสหรือไม่ ไม่น่าแปลกใจค่าปกติที่เกิดเหตุขึ้น แต่มากน้อยกว่าวิธีการ FFT ซึ่งมีระดับสูงของอัตราบวกปลอมที่จะเป็นประโยชน์ในการประยุกต์ใช้ของฉัน
ฉันคิดวิธีแก้ปัญหาที่แตกต่างออกไปโดยสิ้นเชิง ฉันต้องการวิเคราะห์เฟรมภาพนิ่งของวิดีโอเพื่อค้นหาเฟรมที่คมชัดที่สุดในทุกเฟรม (X) ด้วยวิธีนี้ฉันจะตรวจจับการเคลื่อนไหวเบลอและ / หรือภาพไม่ชัด
ฉันลงเอยด้วยการใช้การตรวจจับ Canny Edge และฉันได้ผลลัพธ์ที่ดีมาก ๆ กับวิดีโอเกือบทุกชนิด (ด้วยวิธีของ nikie ฉันมีปัญหากับวิดีโอ VHS แบบดิจิทัลและวิดีโอ interlaced จำนวนมาก)
ฉันปรับประสิทธิภาพให้เหมาะสมด้วยการตั้งค่าภูมิภาคที่น่าสนใจ (ROI) ในภาพต้นฉบับ
ใช้ 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));
}
ขอบคุณ nikie สำหรับคำแนะนำที่ดีเยี่ยมของ Laplace เอกสาร OpenCVชี้ให้ฉันในทิศทางเดียวกัน: ใช้ python, cv2 (opencv 2.4.10) และ numpy ...
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
numpy.max(cv2.convertScaleAbs(cv2.Laplacian(gray_image,3)))
ผลลัพธ์อยู่ระหว่าง 0-255 ฉันพบว่ามีอะไรมากกว่า 200ish อยู่ในโฟกัสมากและโดย 100 มันเบลออย่างเห็นได้ชัด ค่าสูงสุดไม่เคยต่ำกว่า 20 ถึงแม้ว่ามันจะเบลออย่างสมบูรณ์
วิธีหนึ่งที่ฉันใช้วัดการแผ่ของขอบภาพ มองหากระดาษนี้:
@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} }
มันมักจะอยู่หลัง paywall แต่ฉันได้เห็นบางสำเนาฟรี โดยทั่วไปแล้วพวกเขาจะหาขอบแนวตั้งในภาพแล้ววัดความกว้างของขอบเหล่านั้น การเฉลี่ยความกว้างจะให้ผลลัพธ์การประมาณเบลอสุดท้ายของภาพ ขอบที่กว้างขึ้นสอดคล้องกับภาพที่เบลอและในทางกลับกัน
ปัญหานี้เป็นเขตของไม่มีการอ้างอิงการประมาณค่าคุณภาพของภาพ หากคุณค้นหาใน Google Scholar คุณจะได้รับการอ้างอิงที่มีประโยชน์มากมาย
แก้ไข
นี่คือพล็อตของการประมาณการเบลอที่ได้รับจาก 5 ภาพในโพสต์ของ nikie ค่าที่สูงกว่านั้นสอดคล้องกับความพร่ามัวมากขึ้น ฉันใช้ตัวกรอง Gaussian 11x11 ขนาดคงที่และเปลี่ยนค่าเบี่ยงเบนมาตรฐาน (ใช้convert
คำสั่งของ imagemagick เพื่อให้ได้ภาพเบลอ)
หากคุณเปรียบเทียบภาพที่มีขนาดต่างกันอย่าลืมที่จะทำให้ปกติด้วยความกว้างของภาพเนื่องจากภาพที่มีขนาดใหญ่กว่าจะมีขอบที่กว้างขึ้น
ในที่สุดปัญหาที่สำคัญคือการแยกความแตกต่างระหว่างความเบลอของภาพและเบลอที่ไม่ต้องการ (เกิดจากการพลาดโฟกัส, การบีบอัด, การเคลื่อนที่สัมพัทธ์ของตัวแบบกับกล้อง) แต่นั่นไม่ใช่วิธีง่าย ๆ เช่นนี้ สำหรับตัวอย่างของการเบลอทางศิลปะให้ดูที่ภาพของ Lenna: การสะท้อนของ Lenna ในกระจกนั้นพร่ามัว แต่ใบหน้าของเธออยู่ในโฟกัสอย่างสมบูรณ์แบบ สิ่งนี้มีส่วนช่วยในการประมาณการเบลอที่สูงขึ้นสำหรับภาพ Lenna
ฉันพยายามแก้ปัญหาขึ้นอยู่กับตัวกรอง Laplacian จากนี้โพสต์ มันไม่ได้ช่วยอะไรฉัน ดังนั้นฉันลองวิธีแก้ปัญหาจากโพสต์นี้และมันก็ดีสำหรับกรณีของฉัน (แต่ช้า):
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))
ภาพเบลอน้อยลงมีsum
ค่ามากที่สุด!
นอกจากนี้คุณยังสามารถปรับความเร็วและความแม่นยำโดยการเปลี่ยนขั้นตอนเช่น
ส่วนนี้
for x in range(width - 1):
คุณสามารถแทนที่ด้วยอันนี้
for x in range(0, width - 1, 10):
คำตอบข้างต้นอธิบายหลายสิ่งหลายอย่าง แต่ฉันคิดว่ามันมีประโยชน์ที่จะทำให้ความแตกต่างทางความคิด
ถ้าคุณถ่ายภาพโฟกัสที่สมบูรณ์แบบของภาพเบลอ
ปัญหาการตรวจจับการเบลอนั้นเกิดขึ้นเมื่อคุณมีการอ้างอิงเท่านั้น หากคุณต้องการออกแบบเช่นระบบโฟกัสอัตโนมัติคุณเปรียบเทียบลำดับของภาพที่ถ่ายโดยมีระดับการเบลอหรือการปรับให้เรียบและคุณพยายามหาจุดเบลอขั้นต่ำภายในชุดนี้ คำอื่น ๆ ที่คุณต้องอ้างอิงภาพต่าง ๆ โดยใช้หนึ่งในเทคนิคที่แสดงด้านบน (โดยทั่วไป - ด้วยวิธีการปรับแต่งระดับต่างๆที่เป็นไปได้ - มองหาภาพหนึ่งภาพที่มีเนื้อหาความถี่สูงที่สุด)
รหัส Matlab ของสองวิธีที่ได้รับการตีพิมพ์ในวารสารที่ได้รับการยอมรับอย่างสูง (IEEE ธุรกรรมในการประมวลผลภาพ) มีให้ที่นี่: https://ivulab.asu.edu/software
ตรวจสอบอัลกอริทึม CPBDM และ JNBM หากคุณตรวจสอบรหัสมันไม่ยากมากที่จะทำการพอร์ตและบังเอิญว่ามันขึ้นอยู่กับวิธีการของ Marzialiano เป็นคุณสมบัติพื้นฐาน
ฉันใช้มันใช้ fft ใน MATLAB และตรวจสอบฮิสโตแกรมของค่าเฉลี่ยคำนวณ fft และ std แต่ยังฟังก์ชั่นพอดีสามารถทำได้
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(:));
นั่นคือสิ่งที่ฉันทำใน Opencv เพื่อตรวจจับคุณภาพโฟกัสในภูมิภาค:
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];