2010-11-27 9 views
28

은 영리한 연산자에 대한 낮은 및 높은 임계 값은 필수입니다 :자동 계산을 OpenCV에서

매트랩
cvCanny(input,output,thresh1,thresh2) 

가 자동으로 사람들을 계산하는 옵션이있다 :

edge(input,'canny') 

Matlab의 코드를 살펴 보았습니다. 자동으로 계산하는 것은 어렵지 않습니다.

opencv에 대한 자동 임계 값 계산과 함께 canny 연산자의 구현을 알고 있습니까?

감사

+0

이 작업을 수행하는 Matlab 코드를 게시 할 수 있습니까? –

답변

40

. 이 영리한 알고리즘에 대한 자동 임계 값을 결정하기위한 좋은 방법을 찾고 오는 사람을 도움이

희망 ...


이미지가 별개의 전경과 배경, 전경 개체의 다음 가장자리로 구성된 경우

수 사용

  1. 계산 오츠의 임계 값 :

    double otsu_thresh_val = cv::threshold(
        orig_img, _img, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU 
    ); 
    
    에 따라 추출 사용하십시오

    _img은 필요하지 않습니다. 우리는 단지 otsu_thresh_val에만 관심이 있지만 불행히도 OpenCV에서는 임계 값만을 계산할 수있는 방법이 없습니다.

  2. Canny 알고리즘의 경우 오츠의 임계 값을 높은 임계 값으로 사용하고 하위 임계 값의 절반을 사용하십시오. 이 관련

    double high_thresh_val = otsu_thresh_val, 
         lower_thresh_val = otsu_thresh_val * 0.5; 
    cv::Canny(orig_img, cannyOP, lower_thresh_val, high_thresh_val); 
    

this paper: The Study on An Application of Otsu Method in Canny Operator 정보에서 찾을 수있다. Otsu의 구현에 대한 설명은 here입니다.

+0

여기에 CV는 무엇입니까? @VP. – TapanHP

+0

OpenCV @TapanHP –

+0

알겠습니다. 감사합니다. @Dennis – TapanHP

0

루카 델 통고 (Luca Del Tongo)가 제안한 것처럼 회색 이미지에서 임계 값을 계산할 수 있습니다. Java에서 OpenCV를 사용하여 ...

MatOfDouble mu = new MatOfDouble(); 
MatOfDouble stddev = new MatOfDouble(); 
Core.meanStdDev(greyMat, mu, stddev); 
threshold1 = mu.get(0, 0)[0]; 
threshold2 = stddev.get(0, 0)[0]; 
Imgproc.Canny(greyMat, outputMat, threshold1, threshold2); 
+0

여기에 수학이 누락되지 않았습니까? 평균은 일반적으로 편차보다 큽니다. 그래서 나는'threshold1 = mu - stddev'와'threshold2 = mu + stddev'와 같아야한다고 생각합니다. – marsbear

+0

밝은 테이블에있는 하얀 물체의 경우 평균과 편차가 180과 67이됩니다. Canny는 이러한 값으로 가장자리를 감지하지 않습니다. 14와 30은 그 이미지에서 잘 작동합니다. – marsbear

1

동일한 문제에 대한 다른 접근 방식이 있습니다. 이 솔루션은 또한 가장자리 감지를위한 최적의 임계 값을 선택하는 작업을 포함합니다.

  • 먼저 회색 음영 이미지의 중간 값을 계산합니다.
  • 그레이 스케일 이미지의 중간 값 값에 따라 두 값 (상한 및 하한 임계 값)을 선택하십시오.

다음 의사 코드는 수행하는 방법을 보여줍니다 :

v = np.median(gray_img) 
sigma = 0.33 

#---- apply optimal Canny edge detection using the computed median---- 
lower_thresh = int(max(0, (1.0 - sigma) * v)) 
upper_thresh = int(min(255, (1.0 + sigma) * v)) 

은 영리한 에지 검출 기능의 매개 변수로 이러한 임계 값을 수정합니다.

그림 : 통계에서 가우스 곡선을 관찰하면 곡선의 양쪽에서 0.33 사이의 값이 분포에서 고려됩니다. 이 점들 이외의 값은 아웃 라이어로 간주됩니다. 이미지는 데이터로 간주되므로이 개념도 여기에 가정됩니다.

+0

[this] (http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/)를 보았습니까? 아니면 귀하의 이론입니까? – yode

+0

@yod 나는 결코 그것을 가로 질러왔다! 그것을 언급 주셔서 감사합니다! –

3

나는 matlab에 캐니 에지 검출의 소스 코드를보고하고 난 파일 경로가 출력 이미지를 개최하는 장소입니다 OpenCV의 3

private static Mat getpartialedge(Mat image){ 
    double nonEdgeRate = 0.6; 
    double thresholdRate = 0.6; 
    double w = image.cols(); 
    double h = image.rows(); 
    int bins = 256; 
    Mat sobel = new Mat(); 
    Mat sobelx = new Mat(); 
    Mat sobely = new Mat(); 
    Mat sobelxabs = new Mat(); 
    Mat sobelyabs = new Mat(); 
    Size gsz = new Size(5, 5); 
    if(false) { 
     Imgproc.Canny(image, sobel, 41, 71); 
    }else { 

     //Imgproc.GaussianBlur(graycopy,graycopy, gsz, 2); 
     //Imgproc.dilate(image, image, kernel8); 
     Imgproc.GaussianBlur(image, image, gsz, 2); 


     int apertureSize = 3; 
     Imgproc.Sobel(image, sobelx, CvType.CV_16S, 1, 0, apertureSize, 1, 0); 
     Core.convertScaleAbs(sobelx, sobelxabs); 
     Imgproc.Sobel(image, sobely, CvType.CV_16S, 0, 1, apertureSize, 1, 0); 
     Core.convertScaleAbs(sobely, sobelyabs); 
     Core.addWeighted(sobelxabs, 1, sobelyabs, 1, 0, sobel); 
     sobel.convertTo(sobel, CvType.CV_8U); 


     Mat equalized = new Mat(); 
     Imgproc.equalizeHist(sobel, equalized); 
     Imgcodecs.imwrite(filePath + "aftersobel(eq).png", equalized); 
     Imgcodecs.imwrite(filePath + "aftersobel.png", sobel); 


     Mat hist = new Mat(); 
     List<Mat> matList = new ArrayList<Mat>(); 
     matList.add(sobel); 
     Imgproc.calcHist(matList, new MatOfInt(0), new Mat(), hist, new MatOfInt(bins), new MatOfFloat(0f, 256f)); 
     float accu = 0; 
     float t = (float) (nonEdgeRate * w * h); 
     float bon = 0; 
     float[] accutemp = new float[bins]; 
     for (int i = 0; i < bins; i++) { 
      float tf[] = new float[1]; 
      hist.get(i, 0, tf); 
      accu = accu + tf[0]; 
      accutemp[i] = accu; 
      if (accu > t) { 
       bon = (float) i; 
       break; 
      } 
     } 
     Imgproc.threshold(sobel, sobel, bon, 255, Imgproc.THRESH_BINARY); 
     double ut = bon; 
     double lt = thresholdRate * bon; 


     Imgproc.Canny(image, sobel, lt, ut); 
     //Imgproc.dilate(sobel, sobel, kernel2); 
    } 
    return sobel; 
} 

와 자바를 쓸 수 있었다. 그리고 입력 이미지는 U8 데이터 형식의 그레이 스케일 이미지 여야합니다. 기본 원칙은 nonEdgeRate (60 %) 픽셀을 밝기로 비 에지 픽셀로 배제하는 것입니다. 막대 그래프는 밝기를 정렬하는 데 사용되며 위쪽 임계 값은 60 % 미만의 픽셀이되도록 설정됩니다. 하위 임계 값은 상위 임계 값에 thresholdRate (0.6)를 곱하여 설정됩니다.

double nonEdgeRate = 0.6 및 double thresholdRate = 0.6은 제 특정 유스 케이스에서 조정되었습니다. 원본 값은 0.7과 0.4 matlab에 별도로 있습니다.

2

체크 아웃 링크 : http://www.pyimagesearch.com/2015/04/06/zero-parameter-automatic-canny-edge-detection-with-python-and-opencv/

그들은 캐니 에지 검출을위한 낮은 및 높은 임계 값을 결정하기 위해 기본 통계를 사용하여 유사한 솔루션을 구현합니다.

def auto_canny(image, sigma=0.33): 
    # compute the median of the single channel pixel intensities 
    v = np.median(image) 

    # apply automatic Canny edge detection using the computed median 
    lower = int(max(0, (1.0 - sigma) * v)) 
    upper = int(min(255, (1.0 + sigma) * v)) 
    edged = cv2.Canny(image, lower, upper) 

    # return the edged image 
    return edged 
관련 문제