Sharpening Filter

영상의 윤곽선 부분을 강조하게 해주는 필터 입니다. 일반적으로 뭉개진(blur) 영상을 선명하게 하기 위해서 사용 합니다.
영상의 경계부분의 대비효과를 증가시킴으로 마치 영상이 선명해지는 것 같은 효과를 얻게 되는 것입니다.

Filter에서 Kernel 의 사이즈가 클수록 상세한 Edge를 검출할 수가 없으며, 작으면 잡음에 민감해진다.

Roberts : 마스크의 크기가 가장 작고 잡음에 민감하다. (2x2)
Prewitt : 널리 사용되는 것으로 대각 방향의 Edge보다 수평수직의 Edge를 찾는데 사용한다.
Sobel : 수평수직보다 대각선 방향에 놓여진 엣지를 찾는데 사용한다.
출처 : http://forum.falinux.com/zbxe/index.php?document_srl=549723∣=lecture_tip

Sharpening의 방법에는 여러가지 필터가 있는데요, 오늘 살펴볼 필터는 Sobel 필터 입니다.
(다루지 않는 Robert,Prewitt는 위의 출처 페이지를 보시면 됩니다.)

void cv::Sobel (
InputArray     src,
OutputArray     dst,
int     ddepth,
int     dx,
int     dy,
int     ksize = 3,
double     scale = 1,
double     delta = 0,
int     borderType = BORDER_DEFAULT 
)

src : 입력 영상(Mat)
dst : 출력 영상(Mat)
ddepth : 출력영상의 Depth
dx : x축 미분 차수
dy : y축 미분 차수
ksize : Sobel 윈도우의 커널 크기(Filter 크기)
scale :
delta :

3x3 Sobel Kernel & 3x3 Scharr Kernel


Matrix 를 사용한 예제 입니다.

코드
uchar dataA[] { 1,1,1,1,1,1,
                1,1,1,1,1,1,
                1,1,9,9,1,1,
                1,1,9,9,1,1,
                1,1,1,1,1,1,
                1,1,1,1,1,1};

Mat A(6,6,CV_8U,dataA);
int dx = 1, dy = 0;
int ksize = 3;
Sobel(A,dst3,ddepth,dx,dy,ksize);
Sobel(A,dst4,ddepth,dx,dy,-1);
실행결과

설명

Soble fliter에서 gx 필터를 적용한 결과 입니다.


이미지를 사용한 예제 입니다.

코드(주요사용함수, 전체코드는 아래에 첨부)
    int ksize = 3;
    int ddepth = CV_32F;
    int thresh = 100;
    Sobel(srcImage,dstGx,ddepth,1,0,ksize); 
    Sobel(srcImage,dstGy,ddepth,0,1,ksize);
    normalize(abs(dstGx),dstImageGx,0,255,NORM_MINMAX,dtype);
    normalize(abs(dstGy),dstImageGy,0,255,NORM_MINMAX,dtype);
    magnitude(dstGx,dstGy,dstMag);
    normalize(dstMag,dstImageGxy,0,255,NORM_MINMAX,dtype);
    threshold(dstMag,dstImageGxy,thresh,255,THRESH_BINARY);
실행결과

1) x축에 대한 Sobel filter 적용 결과

Sobel(srcImage,dstGx,ddepth,1,0,ksize);
normalize(abs(dstGx),dstImageGx,0,255,NORM_MINMAX,dtype);

x축에 대한 filter를 적용하면 위의 그림과 같이 가로로되어 있는 edge를 검출하는데 부족하다는 것을 볼 수 있습니다.
대각선에 대해서도 검출은 하지만, 아래의 y축의 결과와 비교해보면, 검출하는 부분이 확실히 다른 부분이 있다는 점을 확인 할 수 있었습니다.

2) y축에 대한 Sobel filter 적용 결과

Sobel(srcImage,dstGy,ddepth,0,1,ksize);
normalize(abs(dstGy),dstImageGy,0,255,NORM_MINMAX,dtype);

위와 마찬가지 입니다. x축에 대한 filter 결과와 거의 반대의 결과가 나온 다는 것을 확인 할 수 있습니다.

3) x축과 y축에서 Sobel filter를 적용한 결과

Sobel(srcImage,dstGx,ddepth,1,0,ksize);
Sobel(srcImage,dstGy,ddepth,0,1,ksize);
normalize(abs(dstGx),dstImageGx,0,255,NORM_MINMAX,dtype);
normalize(abs(dstGy),dstImageGy,0,255,NORM_MINMAX,dtype);
magnitude(dstGx,dstGy,dstMag);
normalize(dstMag,dstImageGxy,0,255,NORM_MINMAX,dtype);
threshold(dstMag,dstImageGxy,thresh,255,THRESH_BINARY);

위의 Gx와 Gy의 Sobel filter를 magnitude로 이용해 하나의 Mat으로 변환 합니다.

void cv::magnitude(
        InputArray     x,
        InputArray     y,
        OutputArray     magnitude 
)

아래의 공식을 사용하여 계산 됩니다.

아래는 전체 코드 입니다.

Matrix 로 테스트한 코드
JNIEXPORT jstring JNICALL
Java_com_tistory_technote_opencvandroid_MainActivity_convertNativeLibtoSharpeningSobel(JNIEnv *env, jobject, jlong addrInput, jlong addrResult) {

    Mat &img_input = *(Mat *) addrInput;
    Mat &img_result = *(Mat *) addrResult;
    cvtColor(img_input, img_result, CV_RGBA2GRAY);
    jstring result;
    std::stringstream buffer;
    Mat srcImage = img_result;

    uchar dataA[] { 1,1,1,1,1,1,
                    1,1,1,1,1,1,
                    1,1,9,9,1,1,
                    1,1,9,9,1,1,
                    1,1,1,1,1,1,
                    1,1,1,1,1,1};

    Mat A(6,6,CV_8U,dataA);
    buffer << "A = " <<endl;
    buffer << A << endl;

    int dx = 1, dy = 0;
    int ksize = 3;
    Mat kx,ky;
    getDerivKernels(kx,ky,dx,dy,ksize);
    buffer << "kx = " << kx << endl;
    buffer << "ky = " << ky << endl;

    Mat kxy = ky * kx.t();
    buffer << "kxy = " << kxy << endl;

    int ddepth = CV_16S ;
    Mat dst1;
    sepFilter2D(A,dst1,ddepth,kx,ky);
    buffer << "dst1 = sepFilter2D(A,dst1,ddepth,kx,ky);" << endl;
    buffer << dst1 << endl;

    Mat dst2;
    filter2D(A,dst2,ddepth,kxy);
    buffer << "dst2 = filter2D(A,dst2,ddepth,kxy);" << endl;
    buffer << dst2 << endl;

    Mat dst3;
    Sobel(A,dst3,ddepth,dx,dy,ksize);
    buffer << "dst3 = Sobel(A,dst3,ddepth,dx,dy,ksize);" << endl;
    buffer << dst3 << endl;

    Mat dst4;
    Sobel(A,dst4,ddepth,dx,dy,-1);
    buffer << "dst4 = Sobel(A,dst4,ddepth,dx,dy,-1);" << endl;
    buffer << dst4 << endl;

    Mat dst5;
    Scharr(A,dst5,ddepth,dx,dy);
    buffer << "dst5 = Scharr(A,dst5,ddepth,dx,dy);" << endl;

    const char *cstr = buffer.str().c_str();
    result = env->NewStringUTF(cstr);

    return result;
}
영상을 사용한 예제 코드 입니다.
JNIEXPORT jstring JNICALL
Java_com_tistory_technote_opencvandroid_MainActivity_convertNativeLibtoSharpeningSobel2(JNIEnv *env, jobject, jlong addrInput, jlong addrResult) {

    Mat &img_input = *(Mat *) addrInput;
    Mat &img_result = *(Mat *) addrResult;
    cvtColor(img_input, img_result, CV_RGBA2GRAY);
    jstring result;
    std::stringstream buffer;
    Mat srcImage = img_result;

    int ksize = 3;
    int ddepth = CV_32F;
    int thresh = 100;
    Mat dstGx, dstGy;
    Sobel(srcImage,dstGx,ddepth,1,0,ksize);
    Sobel(srcImage,dstGy,ddepth,0,1,ksize);

    int dtype = CV_8U;
    Mat dstImageGx;
    normalize(abs(dstGx),dstImageGx,0,255,NORM_MINMAX,dtype);

    Mat dstImageGy;
    normalize(abs(dstGy),dstImageGy,0,255,NORM_MINMAX,dtype);

    Mat dstMag;
    magnitude(dstGx,dstGy,dstMag);

    Mat dstImageGxy;
    normalize(dstMag,dstImageGxy,0,255,NORM_MINMAX,dtype);
    threshold(dstMag,dstImageGxy,thresh,255,THRESH_BINARY);
    buffer << "dstImageGxy" << endl;
    img_result = dstImageGxy.clone();

    const char *cstr = buffer.str().c_str();
    result = env->NewStringUTF(cstr);

    return result;
}

관련문의
Gitbook에서 바로 문의하기

results matching ""

    No results matching ""