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

203

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

Сэм
источник
7
Связанный вопрос, который имеет хороший ответ, но также и более сложную формулировку вопроса. stackoverflow.com/questions/5180327/…
Леннарт Роллан
1
У этого также есть намного худшие ответы.
Джон Шедлецкий

Ответы:

133

Да, это так. Вычислите быстрое преобразование Фурье и проанализируйте результат. Преобразование Фурье говорит вам, какие частоты присутствуют на изображении. Если высоких частот мало, изображение размытое.

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

Редактировать :

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

В ответе ники предоставьте такую ​​метрику. Сверните изображение с лапласовым ядром:

   1
1 -4  1
   1

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

Саймон Бергот
источник
9
Единственная проблема - «низкий» и «высокий» также зависят от сцены. +1
Кенни
4
Если ваше изображение не является циклическим, у вас обычно будут острые края на границах изображения, которые приводят к очень высоким частотам
Niki
2
Вы обычно фактически расширяете свое изображение, чтобы избежать этого эффекта. Вы также можете использовать маленькие окна для вычисления локального FFT.
Саймон Бергот
6
Только один момент, который чрезвычайно важен, - это то, что вы должны знать (по крайней мере, приблизительно), каково было ваше ожидаемое содержание (частота) предварительно размытого изображения. Это верно, поскольку частотный спектр будет таким же, как у исходного изображения, умноженного на фильтр размытия. Таким образом, если исходное изображение уже имело преимущественно низкие частоты, как вы можете определить, было ли оно размытым?
Крис А.
1
Если вы сделаете фотографию пустой белой диаграммы, у вас не будет возможности определить, является ли изображение размытым или нет. Я думаю, что ОП хочет абсолютное измерение резкости. предварительно размытое изображение может вообще не существовать. Вам нужно немного поработать, чтобы получить правильную метрику, но fft может помочь с этой проблемой. С этой точки зрения, ответ Никки лучше, чем мой.
Саймон Бергот
158

Другой очень простой способ оценить резкость изображения - использовать фильтр Лапласа (или 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}]

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

результат

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), главным образом потому, что этот метод использует только самый сильный контраст в изображении, в то время как БПФ, по сути, представляет собой среднее значение по всему изображению. Функции также уменьшаются быстрее, поэтому может быть проще установить «размытый» порог.

Niki
источник
1
Что делать, если я после меры местного размытия. А именно, у Фотографии есть области, где она размыта и где она резкая. Я хочу иметь карту, которая оценивает уровень размытия на пиксель.
Рой
4
@Drazick: Я не уверен, что это вообще возможно. Например, посмотрите на изображение Лены: есть большие области, где нет контраста (например, кожа Лены), хотя область находится в фокусе. Я не могу придумать, как определить, является ли такая гладкая область «размытой», или отличить ее от не сфокусированной области. Вы должны задать это как отдельный вопрос (возможно, на DSP.SE). Может быть, у кого-то есть идеи получше.
Ники
1
Подходит ли для размытия в движении? или только для размытия как у гауссов?
mrgloom
@pparescasellas Хотели бы вы поделиться своими реализациями. Мне было бы любопытно увидеть их.
chappjc
@JohnBoe Я думаю, что вы хотели спросить pparescasellas
chappjc
79

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

Это в основном обзорная реализация многих алгоритмов измерения фокуса. Если вы хотите прочитать оригинальные статьи, ссылки на авторов алгоритмов приведены в коде. Бумага 2012 года Pertuz, et al. Анализ операторов измерения фокуса для формы от фокуса (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;
}

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

mevatron
источник
в алгоритме Тененграда, что будет номинальным значением для kSize?
Ман
@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, который должен иметь высокий уровень ложных срабатываний, чтобы быть полезным в моем приложении.

Yaur
источник
Какова будет пороговая ценность, чтобы сказать, что изображение bluryy? Я проверил это. Но это показывает некоторые переменные результаты. Можете ли вы помочь мне в этом, чтобы установить порог?
2vision2
Также попробовал ваше предложение, но числа, которые я получаю, немного случайны. Если я начну новый вопрос относительно этой конкретной реализации, не могли бы вы взглянуть? \
Stpn
@stpn Правильный порог зависит от сцены. В моем приложении (CCTV) я использую пороговое значение по умолчанию, равное 300. Для камер, где это слишком мало, кто-то из техподдержки изменит настроенное значение для этой конкретной камеры.
Яур
почему maxLap = -32767; ?
Клемент Прем
Мы ищем самый высокий контраст, и так как мы работаем со шортами со знаком, -32767 - это наименьшее возможное значение. Прошло 2,5 года с тех пор, как я написал этот код, но у IIRC у меня были проблемы с использованием 16U.
Яур
23

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

В итоге я обнаружил Canny Edge и получил ОЧЕНЬ ОЧЕНЬ хорошие результаты почти с каждым видом видео (при использовании метода nikie у меня были проблемы с оцифрованными 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));
}
Goldorak84
источник
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, даже если он полностью размыт.

ggez44
источник
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 Scholar, вы получите много полезных ссылок.

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

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

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

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

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

mpenkov
источник
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):
Exterminator13
источник
4

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

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

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

Изумрудное оружие
источник
2
Другими словами, это относительное понятие, можно только определить, является ли изображение более или менее размытым, чем другое подобное изображение. т.е. если он имеет более или менее высокочастотный контент в своем БПФ. Частный случай: что, если изображение имеет смежные пиксели с максимальной и минимальной яркостью? Например, полностью черный пиксель рядом с полностью белым пикселем. В этом случае это идеальный фокус, иначе будет более плавный переход от черного к белому. Идеальная фокусировка маловероятна в фотографии, но вопрос не указывает источник изображения (это может быть сгенерировано компьютером).
Бен
1

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

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

Marco
источник
1

Я реализовал это, используя 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(:));
user3452134
источник
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];
Надав Б
источник