edge detection & line detection

David8·2022년 9월 29일
0

컴퓨터비전

목록 보기
9/17

edge detection

  1. 용어

    1. edge pixel: 이미지 intensity가 급격하게 변하는 픽셀
    2. edge: edge pixel 집합
  2. 에지 검출 방법

    1. 1차원 영상
      1. 1차 미분 사용 --> 1차 미분 했을 때 0이 아닌 부분을 활용
    2. 2차원 영상
      1. image gradient 사용
        1. 용어
          1. gradient: x축 방향으로 편미분하고, y축 방향으로 편미분 한 값으로 이루어져 있는 벡터
          2. gradient 크기: 미분 값을 제곱해서 더한 후 루트 씌운 값
          3. gradient 각도: arctan x/y 값
        2. gradient vector 이동
          1. gradient 방향: 현재 픽셀에서 가장 급격하게 변하는 방향
          2. 에지 방향: gradient 방향과 수직
          3. gradient와 gradeint 방향을 구하면 에지의 방향 검출 가능 --> 대각선 픽셀끼리 같은 에지가 검출되면 해당 부분은 에지로 판단할 수 있음!
  3. 종류

    1. 선행조건: 잡음이 있을 경우 미분값이 정확하지 않으므로 noise filtering 후 에지 검출을 수행

    2. sobel operator

      1. 소벨필터로 중심값에 더 큰 가중치를 주어 smoothing 효과를 주고, 값의 차이를 크게 만들어 edge가 잘 검출 되도록 함
        1. Thresholding on magnitude of gradient....?(임계값)
    3. canny edge detector

      1. 순서

        1. 가우시안 필터를 사용하여 영상 내 잡음 제거

        2. 소벨 에지 마스크 활용하여 gradient 크기와 각도 계산

        3. nonmaxima suppression 수행 --> edge가 두꺼워지는 것을 방지하여 edge를 얇게 유지해줌

          1. gradient 방향으로 𝛼(𝑥, 𝑦)와 인접한 픽셀들을 찾는다. (𝛼 : gradient direction)
          2. 𝛼(𝑥, 𝑦)가 인접한 픽셀들의 gradient 크기보다 작다면 제거한다.(값을 0으로 만든다. → 𝛼(𝑥, 𝑦)가 엣지가 될 가능성이 사라진다.)
          3. 따라서, 주변 픽셀들 중 최대치만 남기고 최대치가 아닌 nonmaxima 성분을 제거하는 것이다.
        4. double thresholding 수행 & connectivity analysis to detect and link edges
          1. M(x,y) >= Th -> edge
          1. Th, Tl은 사용자가 정의

          1. M(x,y) < Tl -> non-edge
          2. 사이값 -> edge라고 판별된 픽셀과 연결되어 있으면 edge, 그렇지 않은 경우는 non-edge로 간주
          int main() {
          
           Mat image, canny;
           image = imread("lena.png", 0);
           
           //performs canny edge detection
           //image: input Mat, canny: output Mat 
           //190: Thresh_low of double thresholding 
           //200: Thresh_high of double thresholding 
           //3: aperture size of the Sobel operation 
           Canny(image, canny, 190, 200, 3);
           
           imshow("Input image", image); 
           imshow("canny", canny);
           
           waitKey(0); 
           }
          

        위의 canny edge detector 경우 소벨 에지보다 적은 수의 픽셀만 에지라고 판단됨

line detection

  1. 허프 변환 개념

    1. y=ax+b -> b=-ax+y
      1. 한 점이 가질 수 있는 직선을 a와 b의 평면에 하나의 직선으로 나타냄
      2. y=ax+b는 x=k와 같은 직선을 나타낼 때 a가 무한대가 되므로 --> b =-ax+y의 형태로 바꿈
    2. 에지 영상에서 가능한 (a,b) 조합을 구함
    3. 각 에지 픽셀이 통과하는 직선을 모두 찾은 다음 (a,b)의 조합이 여러번 활용될 경우 그것이 영상에 존재하는 선의 방정식일 확률이 높음
    4. b=-ax+y 직선의 값을 𝜌와𝜃를 이용하여 𝜌𝜃 값으로 나타낼 수 있음(= 𝑥𝑐𝑜𝑠𝜃 + 𝑦𝑠𝑖𝑛𝜃 = 𝜌, 이렇게도 변환 가능)
    5. 𝜌: 원전에서 직선에 수선을 내렸을 때 수선의 길이
    6. 𝜃: p와 x축이 이루는 각도
  2. 알고리즘

    1. 이진 영상으로 변환
    2. 에지 영상 획득
    3. 𝜌𝜃 평면에서 구획 지정 -> 𝜌와𝜃 간격 설정
    4. 에지를 이루는 점들에 대하여 𝜌와𝜃를 계산하여 각 구획에 vote
    5. 문턱값 이상의 vote를 받은 구간에서의 𝜌와𝜃를 직선으로 간주
  3. 원 검출

    1. 허프 변환을 원에 대해서도 동일하게 적용 가능
    2. (𝑥 − 𝑐1)^2+(𝑦 − 𝑐2)^2= 𝑐3 원의 방정식에서 c1, c2, c3가 반복적으로 사용된다면 패러미터들이 표현하는 원 검출
  4. 코드

    HoughLines

    int main() {
      Mat image, edge, result;
      
      float rho, theta, a, b, x0, y0;
      Point p1, p2;
      vector<Vec2f> lines;
      image = imread("chess_pattern.png"); 
      result = image.clone();
      
      cvtColor(image, image, CV_BGR2GRAY); 
      Canny(image, edge, 50, 200, 3); // line detection 전에 edge detection 수행
      
      //applying Hough Transform to find lines in the image
      //edge: input Mat, lines: output vector of lines
      //1: (rho) distance resolution of the accumulator in pixels 
      //CV_PI/180: (theta) angle resolution of the accumulator in radians 
      //150: (threshold) accumulator threshold parameter
      //minimum angle to check for lines. Must fall between 0 and max_theta. 
      //maximum angle to check for lines. Must fall between min_theta and CV_PI 
      HoughLines(edge, lines, 1, CV_PI / 180, 150,0,CV_PI);
      
      for (int i = 0; i < lines.size(); i++) { // line 그리는 작업
      
          rho = lines[i][0];
          theta = lines[i][1]; 
          a = cos(theta);
          b = sin(theta);
    
          x0 = a * rho; 
          y0 = b * rho;
    
          p1 = Point(cvRound(x0 + 1000 * (-b)), cvRound(y0 + 1000 * a)); 
          p2 = Point(cvRound(x0 - 1000 * (-b)), cvRound(y0 - 1000 * a));
    
          line(result, p1, p2, Scalar(0, 0, 255), 3, 8);
      
      }
      imshow("Input image", image); 
      imshow("edge", edge); 
      imshow("Hough Transform", result); 
      waitKey(0);
     }

    HoughLinesP

    int main() {
      Mat image, edge, result;
      vector<Vec4i> lines;
    image = imread("chess_pattern.png"); result = image.clone();
    cvtColor(image, image, CV_BGR2GRAY); 
    Canny(image, edge, 50, 200, 3);
    //edge: input Mat, lines: output vector of lines
    //1: (rho) distance resolution of the accumulator in pixels 
    //CV_PI/180: (theta) angle resolution of the accumulator in radians 
    //50: (threshold) accumulator threshold parameter
    //10: (minLineLength) minimum line length.
    //300: (maxLineGap) Maximum allowed gap between points on the sa me line to link them
    HoughLinesP(edge, lines, 1, CV_PI / 180, 50, 10, 300);
    
    for (int i = 0; i < lines.size(); i++) { 
      Vec4i l = lines[i];
      line(result, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, 8);
    }
    
    imshow("Input image", image); 
    imshow("edge", edge); 
    imshow("Hough Transform", result); 
    waitKey(0);

    }

  5. HoughLines()와 HoughLinesP()의 차이

    1. HoughLines()는 rho와 theta를 계산하여 직선을 반환
      1. 결과
        1. vector lines
        2. i번째 라인의 값은 i번째 검출된 라인의 rho와 theta 값을 가진다.
      2. default parameters:
        1. HoughLines()는 rho와 theta에 대해 default 값을 가진다.
        2. 이 값들은 minimum과 maximum angle을 체크하기 위한 것이다.
    2. HoughLinesP()는 각 라인의 두 점을 계산하여 직선을 반환
      1. vector lines
      2. i번째 라인의 값은 한 점에 대해 (x,y) 값을 가지고 다른 (x, y) 값은 다른 i번쨰 검출된 직선의 값이 된다.
      3. HoghLinesP()는 minimum line length와 같은 line segment에 대해서 default parameter를 가진다


0개의 댓글