이미지가 흐릿한지를 감지하는 방법이 있습니까?


답변:


133

그렇습니다. 고속 푸리에 변환을 계산하고 결과를 분석하십시오. 푸리에 변환은 이미지에 어떤 주파수가 있는지 알려줍니다. 고주파수가 적은 경우 이미지가 흐릿합니다.

'낮음'과 '높음'이라는 용어를 정의하는 것은 당신에게 달려 있습니다.

편집 :

주석에서 언급했듯이 주어진 이미지 의 흐릿함 을 나타내는 단일 플로트를 원하면 적절한 메트릭을 계산해야합니다.

nikie의 답변 은 이러한 지표를 제공합니다. Laplacian 커널로 이미지를 관련 시키십시오.

   1
1 -4  1
   1

그리고 출력에서 ​​강력한 최대 메트릭을 사용하여 임계 값에 사용할 수있는 숫자를 얻습니다. 라플라시안을 계산하기 전에 이미지가 너무 매끄러 워지지 않도록하십시오. 매끄럽게 된 이미지가 실제로 흐릿하다는 것을 알기 때문입니다. :-)


9
'낮음'과 '높음'도 장면에 따라 다릅니다. +1
kenny

4
이미지가 주기적이지 않으면 이미지의 가장자리에 가장자리가 날카 로워 매우 높은 주파수가 발생합니다.
Niki

2
이 효과를 피하기 위해 일반적으로 이미지를 사실상 확장합니다. 작은 창을 사용하여 로컬 fft를 계산할 수도 있습니다.
Simon Bergot

6
매우 중요한 한 가지 점은 예상되는 사전 흐리게 처리 된 이미지 (빈도) 내용이 무엇인지 (적어도 대략) 알아야한다는 것 입니다. 주파수 스펙트럼이 원래 이미지와 블러 링 필터의 시간을 곱하기 때문입니다. 따라서 원본 이미지의 주파수가 이미 낮았다면 이미지가 흐려 졌는지 어떻게 알 수 있습니까?
Chris A.

1
빈 흰색 차트의 사진을 찍으면 이미지가 흐릿한 지 여부를 알 수 없습니다. OP는 절대적인 선명도 측정을 원한다고 생각합니다. 사전 흐리게 처리 된 이미지가 전혀 없을 수 있습니다. 올바른 메트릭을 얻으려면 약간의 노력을 기울여야하지만 fft는이 문제를 해결하는 데 도움이 될 수 있습니다. 이러한 관점에서, nickie의 대답은 나의 것보다 낫습니다.
Simon Bergot

158

이미지의 선명도를 추정하는 또 다른 매우 간단한 방법은 Laplace (또는 LoG) 필터를 사용하여 간단히 최대 값을 선택하는 것입니다. 노이즈가 예상되는 경우 99.9 % 분위수와 같은 강력한 측정 값을 사용하는 것이 좋습니다 (예 : 가장 높은 대비 대신 N 번째로 높은 대비 선택). 이미지 밝기가 변할 것으로 예상되는 경우 이미지 밝기를 정규화하기위한 전처리 단계도 포함해야합니다. 대비 (예 : 히스토그램 등화).

나는 Mathematica에서 Simon의 제안과 이것을 제안했으며 몇 가지 테스트 이미지에서 시도했습니다.

테스트 이미지

첫 번째 테스트는 다양한 커널 크기의 가우시안 필터를 사용하여 테스트 이미지를 흐리게 한 다음 흐릿한 이미지의 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 vs 3.3). 주로이 방법은 이미지에서 가장 강한 대비 만 사용하고 FFT는 기본적으로 전체 이미지에 대한 평균이기 때문입니다. 기능도 더 빨리 감소하므로 "흐리게"임계 값을 설정하는 것이 더 쉬울 수 있습니다.


1
로컬 블러를 측정 한 경우 어떻게됩니까? 즉, 사진에는 흐릿하고 선명한 영역이 있습니다. 픽셀 당 블러 레벨을 추정하는 맵을 갖고 싶습니다.
Royi

4
@ Drazick : 그것이 가능한지 확실하지 않습니다. 예를 들어 Lena 이미지를보십시오. 초점이 맞았지만 대비가없는 넓은 영역이 있습니다 (예 : Lena의 피부). 매끄러운 영역이 "흐리게"보이는지 또는 초점이 맞지 않는 영역과 구별 할 수있는 방법을 생각할 수 없습니다. 이 질문은 별도의 질문으로해야합니다 (DSP.SE에있을 수도 있음). 다른 사람이 더 나은 아이디어를 가지고있을 수도 있습니다.
Niki

1
모션 블러에 적합합니까? 또는 가우시안처럼 흐림에만?
mrgloom

@pparescasellas 구현 내용을 기꺼이 공유 하시겠습니까? 나는 그들을보고 궁금하다.
chappjc

@JohnBoe 나는 당신이 pparescasellas를 요구한다고 생각합니다
chappjc

79

자동 초점 렌즈로 작업하는 동안 이미지 초점감지하는 매우 유용한 알고리즘을 발견했습니다 . MATLAB으로 구현되었지만 대부분의 기능은 filter2D 로 OpenCV로 이식하기가 매우 쉽습니다 .

기본적으로 많은 초점 측정 알고리즘의 설문 조사 구현입니다. 원본 논문을 읽으려면 알고리즘 작성자에 대한 참조가 코드에 제공됩니다. Pertuz 등의 2012 논문. SFF ( shape from focus)에 대한 초점 측정 연산자 분석을 통해 이러한 측정뿐만 아니라 성능 (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;
}

이러한 조치가 문제에 가장 적합한 지 여부를 보장하지는 않지만 이러한 조치와 관련된 논문을 추적하면 더 많은 통찰력을 얻을 수 있습니다. 코드가 유용하기를 바랍니다. 나도 알아


tenengrad 알고리즘에서 kSize의 공칭 값은 얼마입니까?
mans

@mans 일반적으로 이미지의 해상도에 따라 3, 5 또는 7을 사용합니다. 그보다 더 높아야 할 경우 이미지 다운 샘플링을 볼 수 있습니다.
mevatron

32

나이키의 답을 바탕으로합니다. opencv로 laplacian 기반 메소드를 구현하는 것은 간단합니다.

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 방법보다 훨씬 적습니다 .FFT 방법은 내 응용 프로그램에 유용하기 위해 오 탐율이 높아야합니다.


이미지가 흐릿하다고 말하는 임계 값은 얼마입니까? 나는 그것을 테스트했다. 그러나 결과는 다양합니다. 임계 값을 설정하는 데 도움을 주시겠습니까?
2vision2

또한 귀하의 제안을 시도했지만 내가 얻는 숫자는 약간 임의적입니다. 이 특정 구현과 관련하여 새로운 질문을 시작한다면 살펴 보시겠습니까? \
Stpn

@stpn 올바른 임계 값은 장면에 따라 다릅니다. 내 응용 프로그램 (CCTV)에서 나는 기본 임계 값 300을 사용하고 있습니다. 지원이 낮은 사람의 카메라의 경우 특정 카메라에 대해 구성된 값이 변경됩니다.
Yaur

왜 "maxLap = -32767;" ?
Clement Prem

우리는 가장 높은 대비를 찾고 있으며 부호있는 반바지로 작업하기 때문에 -32767이 가장 낮은 값입니다. 코드를 작성한 지 2.5 년이 지났지 만 IIRC에서는 16U를 사용하는 데 문제가있었습니다.
Yaur

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));
}

17

멋진 라플라스 제안에 감사드립니다. OpenCV 문서 는 파이썬, 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 미만이되지 않습니다.


3
사진 3 장에 255 장을 받았습니다. 완벽하게 초점을 맞춘 사진 하나에 108 개를 얻었습니다. 따라서이 방법의 효과는 무언가에 달려 있다고 생각합니다.
WindRider

@WindWider와 동의했습니다. 이것이 실패한 샘플 이미지는 이 이미지 라고 생각합니다. 이미지가 흔들 리더라도 이미지의 대비와 픽셀 간의 해당 강도 차이가 커서 라플라시안 값이 상대적으로 크기 때문입니다. 내가 틀렸다면 정정 해주세요.
Resham Wadhwa

@ReshamWadhwa cc WindRider-ditto-이 문제를 해결하는 방법에 대한 아이디어가 있습니까 ??
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에서 찾아 보면 유용한 참고 자료를 많이 얻을 수 있습니다.

편집하다

다음은 nikie의 게시물에서 5 개의 이미지에 대해 얻은 흐림 추정치의 도표입니다. 값이 클수록 흐림이 커집니다. 고정 크기 11x11 Gaussian 필터를 사용하고 표준 편차를 변경했습니다 (imagemagick의 convert명령을 사용하여 이미지가 흐려짐 ).

여기에 이미지 설명을 입력하십시오

크기가 다른 이미지를 비교하는 경우 이미지 너비가 커질수록 이미지 너비가 정규화되는 것을 잊지 마십시오.

마지막으로 중요한 문제는 예술적 흐림 효과와 원하지 않는 흐림 효과 (초점 미스, 압축, 카메라에 대한 피사체의 상대적 움직임으로 인한)를 구별하는 것입니다. 예술적 흐림 효과의 예를 보려면 Lenna 이미지를 살펴보십시오. 거울에서 Lenna의 반사가 흐릿하지만 얼굴의 초점이 완벽합니다. 이는 Lenna 이미지에 대한 더 높은 흐림 추정치에 기여합니다.


5

게시물 에서 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):

4

위의 답변은 많은 것을 설명했지만 개념적 구별을하는 것이 유용하다고 생각합니다.

흐릿한 이미지를 완벽하게 초점이 맞춰 촬영하면 어떻게됩니까?

흐림 감지 문제는 참조 가있을 때만 발생합니다 . 예를 들어, 자동 초점 시스템을 설계해야하는 경우 다른 정도의 블러 링 또는 스무딩으로 촬영 한 이미지 시퀀스를 비교하고이 세트 내에서 최소 블러 링 지점을 찾으려고합니다. 다시 말하면 위에서 설명한 기법 중 하나를 사용하여 다양한 이미지를 상호 참조해야합니다 (기본적으로-접근 방식에서 다양한 수준의 세분화가 가능-가장 높은 빈도의 콘텐츠가있는 하나의 이미지를 찾습니다).


2
즉, 상대적인 개념이므로 이미지가 다른 유사한 이미지보다 다소 흐려지는 지 여부 만 알 수 있습니다. 즉, FFT에 고주파수 컨텐츠가 다소있는 경우. 특별한 경우 : 이미지에 최대 및 최소 광도가있는 인접 픽셀이있는 경우 어떻게해야합니까? 예를 들어 완전히 흰색 픽셀 옆에 완전히 검은 색 픽셀이 있습니다. 이 경우 완벽한 초점이며, 그렇지 않으면 검은 색에서 흰색으로 부드럽게 전환됩니다. 사진에는 ​​완벽한 초점이 아니지만 문제는 이미지의 출처를 지정하지 않습니다 (컴퓨터에서 생성 될 수 있음).
Ben

1

유명한 저널 (IEEE Transactions on Image Processing)에 게시 된 두 가지 방법의 Matlab 코드는 여기에서 확인할 수 있습니다 : https://ivulab.asu.edu/software

CPBDM 및 JNBM 알고리즘을 확인하십시오. 코드를 확인하면 이식하기가 어렵지 않고 우연히 Marzialiano의 방법을 기본 기능으로 사용합니다.


1

MATLAB에서 fft를 사용하고 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(:));

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];
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.