Чи є спосіб виявити, чи зображення розмите?


203

Мені було цікаво, чи є спосіб визначити, чи розмите зображення, чи не аналізуючи дані зображення.


7
Супутнє запитання, яке має хорошу відповідь, але також більш причетне формулювання питань. stackoverflow.com/questions/5180327/…
Lennart Rolland

1
Він також має набагато гірші відповіді.
Іван Шедлецький

Відповіді:


133

Так. Обчисліть Швидке перетворення Фур'є та проаналізуйте результат. Перетворення Фур'є повідомляє вам, які частоти є в зображенні. Якщо низька кількість високих частот, то зображення розмито.

Визначення термінів "низький" та "високий" залежить від вас.

Редагувати :

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

відповідь nikie надає таку метрику. Оберніть зображення лапласіанським ядром:

   1
1 -4  1
   1

І використовуйте надійний максимальний показник на виході, щоб отримати число, яке ви можете використовувати для визначення порогу. Постарайтеся уникати занадто згладжування зображень перед тим, як обчислити лапласіанців, адже ви лише дізнаєтесь, що згладжене зображення справді розмите :-).


9
Тільки проблема "низький" і "високий" також залежать від сцени. +1
kenny

4
Якщо ваше зображення не циклічне, зазвичай у вас будуть гострі краї на межах зображення, які призводять до дуже високих частот
Niki

2
ви зазвичай практично розширюєте своє зображення, щоб уникнути цього ефекту. ви також можете використовувати невеликі вікна для обчислення локального ффта.
Саймон Берго

6
Надзвичайно важливий лише один момент - ви повинні знати (принаймні приблизно), який у вас очікуваний попередньо розмитий (частотний) вміст зображення. Це вірно, оскільки частотний спектр буде таким, як початковий час зображення, ніж фільтр, що розмивається. Таким чином, якщо вихідне зображення вже мало переважно низькі частоти, як ви можете сказати, чи було воно розмитим?
Кріс А.

1
Якщо ви сфотографуєте порожню білу діаграму, ви не можете сказати, розмита чи ні. Я думаю, що ОП хоче деякого абсолютного вимірювання різкості. попередньо розмитого зображення може взагалі не існувати. Вам доведеться трохи попрацювати, щоб скласти правильну метрику, але fft може допомогти у цій проблемі. У цій перспективі відповідь нікі є кращою, ніж моя.
Саймон Берго

158

Ще один дуже простий спосіб оцінити чіткість зображення - використовувати фільтр Лапласа (або LoG) і просто вибрати максимальне значення. Використовувати надійну міру, наприклад, 99,9% -ний квантил, ймовірно, краще, якщо ви очікуєте шуму (тобто вибору найнижчого контрасту замість найбільшого контрасту). Якщо ви очікуєте різної яскравості зображення, вам слід також включити крок попередньої обробки для нормалізації яскравості зображення / контраст (наприклад, вирівнювання гістограми).

Я реалізував пропозицію Саймона та цю у Mathematica і спробував її на кількох тестових зображеннях:

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

Перший тест розмиває тестові зображення, використовуючи фільтр Гаусса з різним розміром ядра, потім обчислює 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}]

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

fft результат

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 проти 3,3), головним чином тому, що цей метод використовує лише найсильніший контраст у зображенні, тоді як FFT по суті є середнім для всього зображення. Функції також зменшуються швидше, тому може бути простіше встановити "розмитий" поріг.


1
Що робити, якщо я після міри місцевої розмитості. А саме, на фотографії є ​​ділянки, де вона розмита і де різка. Я хочу мати карту, яка оцінює рівень розмитості на піксель.
Рой

4
@Drazick: Я не впевнений, чи можливо це навіть можливо. Наприклад, подивіться на зображення Лени: Є великі ділянки, де немає контрасту (наприклад, шкіра Лени), хоча область зосереджена на фокусі. Я не можу придумати спосіб визначити, чи є така гладка зона «розмитою», або відрізнити її від зони поза фокусом. Ви повинні задати це окремим питанням (можливо, на DSP.SE). Можливо, хтось інший має кращі ідеї.
Нікі

1
Чи підходить воно для розмиття руху? чи лише для розмиття, як гаусса?
mrgloom

@pparescasellas Ви бажаєте поділитися своїми реалізаціями. Мені було б цікаво їх побачити.
chappjc

@JohnBoe Я думаю, ти мав на увазі запитати pparescasellas
chappjc

79

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

Це в основному опитування впровадження багатьох алгоритмів вимірювання фокусу. Якщо ви хочете прочитати оригінальні статті, в коді наведено посилання на авторів алгоритмів. Документ Pertuz 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)
        [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;
}

Ніяких гарантій щодо того, чи є ці заходи найкращим вибором для вашої проблеми, але якщо ви відстежите документи, пов’язані з цими заходами, вони можуть дати вам більше розуміння. Сподіваємось, ви знайдете код корисним! Я знаю, що зробив.


в алгоритмі tenengrad, яке б було номінальне значення для kSize?
mans

@ mans Я зазвичай використовую 3, 5 або 7, залежно від роздільної здатності зображення. Якщо ви виявите, що вам потрібно піднятися вище, ви можете подивитися на зменшення зображення.
mevatron

32

Будівництво відповіді Nike. Це реально реалізувати метод, що базується на лапласіанах, з 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, який повинен бути корисним для моєї програми.


Яке значення порогу можна сказати, коли зображення є розмитим? Я це протестував. Але його показ показує різні результати. Чи можете ви мені допомогти в цьому, щоб встановити поріг?
2vision2

Також спробував вашу пропозицію, але цифри, які я отримую, трохи випадкові. Якщо я розпочну нове запитання щодо цієї конкретної реалізації, ви хочете поглянути? \
Stpn

@stpn Правий поріг залежить від сцени. У своїй програмі (відеоспостереження) я використовую поріг за замовчуванням 300. Для камер, де це низький рівень, хтось із підтримки змінить налаштоване значення для конкретної камери.
Яур

чому "maxLap = -32767;" ?
Климент Прем

Ми шукаємо найвищий контраст, і оскільки ми працюємо з підписаними шортами -32767 - це найменше можливе значення. Минуло 2,5 роки, як я написав цей код, але у IIRC у мене виникли проблеми з використанням 16U.
Яур

23

Я придумав зовсім інше рішення. Мені потрібно було проаналізувати кадри відео, щоб знайти найгостріший у кожному (X) кадрі. Таким чином, я б виявив розмиття руху та / або зображення із фокусом.

Я в кінцевому підсумку використовував детектування Canny Edge, і я отримав ДУЖЕ ДУЖЕ хороші результати майже з усіма видами відео (за методом Нікіє, у мене були проблеми з оцифрованими відео VHS та важкими переплетеними відео).

Я оптимізував ефективність, встановивши область інтересу (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));
}

17

Дякую нікею за чудову пропозицію Лапласа. Документи 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. Я виявив, що все, що перевищує 200сот, знаходиться в центрі уваги, а на 100 - це помітно розмито. макс ніколи не отримує значно менше 20, навіть якщо він повністю розмитий.


3
Я отримав 255 за 3 свої фотографії. І за одну ідеально зосереджену фотографію я отримав 108. Отже, я думаю, ефективність методу залежить від чогось.
WindRider

Погоджено з @WindWider. Зразкове зображення, де цього не вдається, це зображення, але я думаю, що причина полягає в тому, що, хоча зображення хитке, контрастність зображення та відповідні різниці інтенсивності між пікселями великі, через що значення Лаплаціана відносно великі. Будь ласка, виправте мене, якщо я помиляюся.
Решам Вадва

@ReshamWadhwa cc WindRider - дітто - якісь ідеї, як це виправити ??
jtlz2

@ ggez44 Це моя краща відповідь - але значення є функцією від кількості пікселів на зображенні. Чи знаєте ви, як це масштабно теоретично? Я міг би задати це як нове запитання, але, швидше за все, він буде збитий. Дякую!
jtlz2

10

Один із способів, якими я зараз користуюся, вимірює поширення країв у зображенні. Шукайте цей документ:

@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 Академія, ви отримаєте багато корисних посилань.

EDIT

Ось сюжет оцінок розмитості, отриманих для 5 зображень у посту нікі. Більш високі значення відповідають більшому розмитості. Я використав фільтр Гаусса фіксованого розміру 11x11 і змінив стандартне відхилення (використовуючи convertкоманду imagemagick для отримання розмитих зображень).

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

Якщо ви порівнюєте зображення різного розміру, не забудьте нормалізуватися за шириною зображення, оскільки більші зображення матимуть більш широкі краї.

Нарешті, суттєвою проблемою є розмежування художньої розмитості та небажаної розмитості (спричинена промахом фокусування, стисненням, відносним рухом об’єкта на камеру), але це виходить за рамки простих підходів, як цей. Для прикладу художньої розмитості подивіться на образ Ленни: відображення Ленни в дзеркалі розмито, але її обличчя ідеально зосереджене. Це сприяє більш високій оцінці розмитості зображення Ленни.


5

Я спробував рішення на основі фільтра Лаплачіа з цієї посади. Це мені не допомогло. Отже, я спробував рішення з цієї посади, і це було добре для мого випадку (але повільно):

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

4

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

Що робити, якщо ви сфокусуєте ідеально зосереджене зображення розмитого зображення?

Проблема виявлення розмиття добре поставлена ​​лише тоді, коли у вас є посилання . Якщо вам потрібно сконструювати, наприклад, систему автофокусування, ви порівнюєте послідовність зображень, зроблених з різним ступенем розмитості або згладжування, і намагаєтесь знайти точку мінімальної розмитості в цьому наборі. Інші слова, вам потрібно перехрестити різні зображення за допомогою однієї з методів, проілюстрованих вище (в основному - з різними можливими рівнями вдосконалення підходу - шукаючи одне зображення з найвищим високочастотним вмістом).


2
Іншими словами, це відносне поняття, можна лише визначити, чи є зображення більш-менш розмитим, ніж інше подібне зображення. тобто, якщо він має більш-менш високочастотний вміст у своїй FFT. Конкретний випадок: що робити, якщо зображення має сусідні пікселі з максимальною та мінімальною яскравістю? Наприклад, повністю чорний піксель поруч із повністю білим пікселем. У цьому випадку це ідеальний фокус, інакше відбудеться більш плавний перехід від чорного до білого. Ідеальний фокус у фотографії малоймовірний, але питання не визначає джерело зображення (це може бути створено комп'ютером).
Бен

1

Код Matlab з двох методів, опублікованих у високо оцінених журналах (IEEE Transaction on Processing Image), доступний тут: https://ivulab.asu.edu/software

перевірити алгоритми CPBDM та JNBM. Якщо ви перевірите код, його перенести не дуже важко, і, до речі, він заснований на методі Марціаліано як основній функції.


1

Я реалізував це використовувати Fft в matlab і перевірити гістограму середнього обчислення fft і std, але також функцію fit можна зробити

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

Ось що я роблю в 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];
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.