언어/C

C 언어 영상처리 - Sobel Filter, 윤곽선 검출, Edge Detection

이게될까 2024. 5. 7. 18:54
728x90
728x90

2024.05.02 - [언어/C] - C언어 영상처리 Edge 구하기, threshold 구하기

[C언어 영상처리 Edge 구하기, threshold 구하기

edge는 명암, 휘도 등이 급격하게 변하는 곳 입니다.만약 물체가 동일한 색 이라면 경계의 색 차이가 크게 나지 않겠지요 ..그래도 색 차이가 큰 곳에서는 대부분 경계가 잘 드러납니다.x,y에 대한

yoonschallenge.tistory.com](https://yoonschallenge.tistory.com/480)

이전에 진행했던 내용이랑 비슷합니다.

x필터만 적용했을 때

y필터만 적용했을 때

x+y

threshold를 넘긴 부분만 표현했을 때

void sobelEdgeMap(double* y, int width, int height, BITMAPFILEHEADER bmpFile, BITMAPINFOHEADER bmpInfo, double* edgey) {
    //padding
    int padding = 2, pwidth = width + padding * 2, pheight = height + padding * 2, psize = pwidth * pheight;
    double* py, * xy, * yy, * outy, sumf = 0;

    py = (double*)calloc(pwidth * pheight, sizeof(double));
    xy = (double*)calloc(width * height, sizeof(double));
    yy = (double*)calloc(width * height, sizeof(double));
    outy = (double*)calloc(width * height, sizeof(double));
    int fsize = padding*2+1;

    double* xfilter,* yfilter;
    xfilter = (double*)calloc(fsize * fsize, sizeof(double));
    yfilter = (double*)calloc(fsize * fsize, sizeof(double));
    double xco, yco;
    for (int i = 0; i < fsize; i++) {
        for (int j = 0; j < fsize; j++) {
            xco = (i - padding);
            yco = (j - padding);
            if (xco ==0 && yco == 0) {
                xfilter[i * fsize + j] = 0;
                yfilter[i * fsize + j] = 0;
            }
            else {
                xfilter[i * fsize + j] = xco / (xco * xco + yco * yco);
                yfilter[i * fsize + j] = yco / (xco * xco + yco * yco);
            }
        }
    }


    applyPaddingWithAverage(py, height, width, padding, y);
    calFilter(xy, py, fsize, xfilter, height, width, pwidth);
    calFilter(yy, py, fsize, yfilter, height, width, pwidth);
    makeOutFile(bmpFile, bmpInfo, "xEdgeOut.bmp", xy);
    makeOutFile(bmpFile, bmpInfo, "yEdgeOut.bmp", yy);
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            outy[j * width + i] = sqrt(xy[j * width + i] * xy[j * width + i] + yy[j * width + i] * yy[j * width + i]);
        }
    }

    CumulativeHisto(height, width, outy, bmpInfo.biSizeImage, (((bmpInfo.biBitCount / 8) * width) + 3) / 4 * 4, bmpFile, bmpInfo);
    printf("threshold= %f\n", threshold);
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            if (outy[j * width + i] > threshold) edgey[j * width + i] = 254;
        }
    }
    makeOutFile(bmpFile, bmpInfo, "EdgeOut.bmp", outy);
    makeOutFile(bmpFile, bmpInfo, "thresholdEdge.bmp", edgey);
    free(py);
    free(xy);
    free(yy);
    free(outy);

}

여러분의 Sobel edge filter 구현을 살펴보았습니다. 전반적으로 필터링 과정을 직접 구현하여 이미지의 에지를 감지하려는 시도는 인상적입니다. 다만, 몇 가지 개선점과 주의점을 지적하고 싶습니다:

  1. 필터 설계: 전형적인 Sobel 필터는 3x3 크기의 필터를 사용하며, 가로 및 세로 에지를 감지하기 위해 특정한 값이 설정되어 있습니다. 하지만 여기서는 필터 크기를 동적으로 생성하고 계산 방식이 전통적인 Sobel 필터와 다르게 보입니다. 각 점에 대해 가중치를 거리의 역수로 설정하여 필터를 적용하는 방식은 일반적인 Sobel 필터의 접근 방식과 다릅니다. Sobel 필터는 일반적으로 다음과 같은 형태를 취합니다:
  2. Gx (수평 필터) Gy (수직 필터) [-1 0 1] [ 1 2 1] [-2 0 2] [ 0 0 0] [-1 0 1] [-1 -2 -1]
  3. 메모리 관리: 메모리를 동적으로 할당하고 해제하는 것은 좋은 접근 방식입니다. 그러나 프로그램의 복잡성과 크기가 커짐에 따라 메모리 누수가 발생할 수 있으므로 할당된 메모리가 모두 해제되었는지 확인하는 것이 중요합니다.
  4. 코드 최적화: 현재 코드에서는 여러 중첩 반복문을 사용하여 필터를 적용하고 있습니다. 이는 효율성을 떨어뜨릴 수 있습니다. 가능한 벡터화된 연산이나 효율적인 알고리즘을 사용하여 성능을 향상시킬 수 있습니다.
  5. 함수 분리: sobelEdgeMap 함수는 매우 많은 작업을 수행하고 있습니다. 이 함수를 더 작은 기능별 함수로 분리하여 코드의 가독성과 유지보수성을 높이는 것이 좋습니다.
  6. 에러 처리: 현재 코드에서는 입력 이미지의 유효성 검사나 함수 호출 결과에 대한 에러 처리가 부족합니다. 사용자가 예상치 못한 입력을 제공했을 때 이를 적절히 처리할 수 있는 로직을 추가하는 것이 중요합니다.
  7. 결과 검증: 코드가 의도대로 정확히 작동하는지 확인하기 위해, 몇 가지 테스트 이미지를 사용하여 결과를 검증하는 것이 좋습니다. 테스트 과정에서 필터의 파라미터를 조정하여 최적의 결과를 도출할 수 있습니다.

코드를 개선하고자 할 때는 이러한 지적 사항들을 참고하여 보다 효과적인 에지 감지 필터를 구현해 볼 수 있습니다. 필터의 특성을 잘 이해하고, 필요에 따라 조정하는 것이 중요합니다.

귀찮으니까 이정도만 보여주고 가겠습니다....

728x90