Есть ли способ обнаружить, что изображение размыто?

Мне было интересно, есть ли способ определить, является ли изображение размытым или нет, анализируя данные изображения.

да. вычислить fft и проанализировать результат. Преобразование Фурье сообщает вам, какие частоты присутствуют в изображении. Если есть небольшое количество высоких частот, тогда изображение размыто.

Определение терминов «низкий» и «высокий» зависит от вас.

отредактируйте : как указано в комментариях, если вы хотите, чтобы один поплавок представлял размытость данного изображения, вам нужно разработать подходящую метрику.

Ответ nikie дает такую ​​метрику. Сконвертировать изображение с kernelм Лапласа:

1 1 -4 1 1 

И используйте надежную максимальную метрику на выходе, чтобы получить число, которое вы можете использовать для порогового значения. Старайтесь избегать сглаживания изображений, прежде чем вычислять лапласиан, потому что вы только узнаете, что сглаженное изображение действительно размыто :-).

Другой очень простой способ оценить резкость изображения – использовать фильтр Laplace (или LoG) и просто выбрать максимальное значение. Использование надежной меры, такой как 99,9% квантиль, вероятно, лучше, если вы ожидаете шума (т. Е. Выбираете N-высокий контраст, а не самый высокий контраст). Если вы ожидаете изменения яркости изображения, вы также должны включить шаг предварительной обработки для нормализации яркости / контраст (например, выравнивание гистограммы).

Я реализовал предложение Саймона и этот в Mathematica, и попробовал его на нескольких тестовых изображениях:

тестовые изображения

Первый тест размывает тестовые изображения с использованием гауссовского фильтра с различным размером ядра, затем вычисляет БПФ размытого изображения и принимает среднее значение на 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}] 

Результат в логарифмическом сюжете:

fft результат

5 строк представляют собой 5 тестовых изображений, ось X представляет собой гауссовский радиус фильтра. Графики уменьшаются, поэтому БПФ является хорошей мерой для резкости.

Это код для оценки «размытости» с самым высоким значением LoG: он просто применяет LoG-фильтр и возвращает самый яркий пиксель в результате фильтра:

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

Результат в логарифмическом сюжете:

результат лапласа

Распространение для не-размытых изображений здесь немного лучше (2.5 против 3.3), главным образом потому, что этот метод использует только самый сильный контраст в изображении, тогда как БПФ является по существу средним значением для всего изображения. Функции также уменьшаются быстрее, поэтому может быть проще установить «размытый» порог.

Во время некоторой работы с объективом с автофокусом я наткнулся на этот очень полезный набор алгоритмов для обнаружения фокусировки изображения . Он реализован в MATLAB, но большинство функций довольно легко переносить в OpenCV с помощью filter2D .

Это в основном обзорная реализация многих алгоритмов измерения фокусировки. Если вы хотите прочитать оригинальные статьи, в коде содержатся ссылки на авторов алгоритмов. В статье 2012 г. Пертуз и др. Анализ операторов фокусировки для формы из фокуса (SFF) дает отличный обзор всех этих показателей, а также их производительности (как с точки зрения скорости, так и точности применительно к SFF).

EDIT: Добавлен код 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) [MN] = 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(FMImage); 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) [MN] = 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 %****************************************************************** - 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) [MN] = 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(FMImage); 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) [MN] = 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_(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; } 

Никаких гарантий относительно того, являются ли эти меры лучшим выбором для вашей проблемы, но если вы отследите документы, связанные с этими мерами, они могут дать вам больше информации. Надеюсь, вы найдете код полезным! Я знаю, что знаю.

Исходя из ответа Найка. Его простой способ реализовать метод лапласиана с помощью 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; } - 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 и тяжелыми чересстрочными видео).

Я оптимизировал производительность, установив интересующую область (ROI) на исходное изображение.

Использование EmguCV:

 //Convert image using Canny using (Image 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 за то великое предложение Лапласа. Документы 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 человек заметно размыто. max никогда не получает намного меньше 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} } 

Обычно это за платной почтой, но я видел несколько бесплатных копий. В основном, они определяют вертикальные края изображения, а затем измеряют ширину этих краев. Усреднение ширины дает окончательный результат оценки размытия для изображения. Большие края соответствуют размытым изображениям и наоборот.

Эта проблема относится к области оценки качества без ссылки . Если вы посмотрите на Google Scholar, вы получите много полезных ссылок.

РЕДАКТИРОВАТЬ

Вот график оценок размытости, полученных для 5 изображений в сообщении nikie. Более высокие значения соответствуют большему размытию. Я использовал гауссовский фильтр фиксированного размера 11×11 и менял стандартное отклонение (используя команду convert imagemagick для получения размытых изображений).

введите описание изображения здесь

Если вы сравниваете изображения разных размеров, не забудьте нормализовать ширину изображения, так как большие изображения будут иметь более широкие края.

Наконец, значительная проблема заключается в различении художественного размытия и нежелательного размытия (вызванного фокусным промахом, сжатием, относительным движением объекта к камере), но это выходит за frameworks простых подходов, подобных этому. Для примера художественного размытия взгляните на изображение Ленны: reflection Ленны в зеркале размыто, но ее лицо полностью сосредоточено. Это способствует более высокой оценке размытия изображения Lenna.

Ответы выше объясняли многие вещи, но я думаю, что полезно сделать концептуальное различие.

Что делать, если вы снимаете изображение с размытым фоном?

Проблема с распознаванием размытия является только хорошей позицией, когда у вас есть ссылка . Если вам нужно разработать, например, систему автофокусировки, вы сравниваете последовательность изображений, сделанных с разной степенью размытия или сглаживания, и вы пытаетесь найти точку минимального размытия внутри этого набора. Другими словами, вам нужно перекрестно ссылаться на различные изображения, используя один из описанных выше методов (в основном – с различными возможными уровнями уточнения подхода – поиск одного изображения с самым высоким высокочастотным контентом).

Я пробовал решение, основанное на фильтре Лапласиана с этого поста. Это мне не помогло. Итак, я попробовал решение с этого поста, и это было хорошо для моего дела (но медленное):

 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 Transactions on Image Processing), доступен здесь: https://ivulab.asu.edu/software

проверьте алгоритмы CPBDM и JNBM. Если вы проверите код, его не очень сложно портировать, и, кстати, он основан на методе Марциалиано как основной функции.

я реализовал его, используя 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]; 
  • Установка ROI с мышью из прямоугольника на видео
  • OpenCv 2.3 C - Как изолировать объект внутри изображения
  • Как поворачивать изображения JPEG на основе метаданных ориентации?
  • Очень быстро memcpy для обработки изображений?
  • Поворот изображения в java
  • Фильтр карты перемещения в OpenCV
  • OpenCV C ++ / Obj-C: Обнаружение листа бумаги / Квадратное обнаружение
  • масштаб и rotation Соответствие шаблонов
  • Как создать и применить фильтр Гаусса в MATLAB без использования fspecial, imfilter или conv2?
  • Каков наиболее эффективный способ отображения декодированных видеокадров в Qt?
  • Как сделать fadein изображения на экране активности Android?
  • Interesting Posts
    Давайте будем гением компьютера.