c++ - 판별 - 허프변환 원 검출




opencv로 견고한(색상 및 크기 불변) 원 검출 작성(Hough 변환 또는 기타 기능 기반) (4)

이미지에서 원을 찾기 위해 다음과 같은 매우 간단한 파이썬 코드를 작성했습니다.

import cv
import numpy as np

WAITKEY_DELAY_MS = 10
STOP_KEY = 'q'

cv.NamedWindow("image - press 'q' to quit", cv.CV_WINDOW_AUTOSIZE);
cv.NamedWindow("post-process", cv.CV_WINDOW_AUTOSIZE);

key_pressed = False
while key_pressed != STOP_KEY:

    # grab image
    orig = cv.LoadImage('circles3.jpg')

    # create tmp images
    grey_scale = cv.CreateImage(cv.GetSize(orig), 8, 1)
    processed = cv.CreateImage(cv.GetSize(orig), 8, 1)


    cv.Smooth(orig, orig, cv.CV_GAUSSIAN, 3, 3)

    cv.CvtColor(orig, grey_scale, cv.CV_RGB2GRAY)

    # do some processing on the grey scale image
    cv.Erode(grey_scale, processed, None, 10)
    cv.Dilate(processed, processed, None, 10)
    cv.Canny(processed, processed, 5, 70, 3)
    cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 15, 15)

    storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)

    # these parameters need to be adjusted for every single image
    HIGH = 50
    LOW = 140

    try: 
        # extract circles
        cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 32.0, HIGH, LOW)

        for i in range(0, len(np.asarray(storage))):
            print "circle #%d" %i
            Radius = int(np.asarray(storage)[i][0][2])
            x = int(np.asarray(storage)[i][0][0])
            y = int(np.asarray(storage)[i][0][1])
            center = (x, y)

            # green dot on center and red circle around
            cv.Circle(orig, center, 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
            cv.Circle(orig, center, Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

            cv.Circle(processed, center, 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
            cv.Circle(processed, center, Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

    except:
        print "nothing found"
        pass

    # show images
    cv.ShowImage("image - press 'q' to quit", orig)
    cv.ShowImage("post-process", processed)

    cv_key = cv.WaitKey(WAITKEY_DELAY_MS)
    key_pressed = chr(cv_key & 255)

다음 두 가지 예에서 알 수 있듯이 '원 찾기 품질'은 매우 다양합니다.

사례 1 :

사례 2 :

Case1과 Case2는 기본적으로 동일한 이미지이지만 여전히 알고리즘이 다른 원을 감지합니다. 알고리즘에 다른 크기의 원이있는 이미지를 표시하면 원 검출이 완전히 실패 할 수도 있습니다. 이는 주로 각각의 새 사진에 대해 개별적으로 조정해야하는 HIGHLOW 매개 변수 때문입니다.

따라서 내 질문 : 이 알고리즘을보다 강력하게 만들 수있는 다양한 가능성은 무엇입니까? 크기와 색상이 일정하지 않아야 서로 다른 색상과 크기의 서로 다른 원이 감지됩니다. 어쩌면 Hough 변환을 사용하는 것이 최선의 방법이 아닌가? 더 나은 접근법이 있습니까?


Hough 변환은 "모델"을 사용하여 모서리가 감지 된 이미지에서 특정 피쳐를 찾습니다. HoughCircles 의 경우 모델은 완벽한 원입니다. 즉, 오탐 (false positive)의 수를 늘리지 않고도 사진에서 더 이상하지 않고 타원 모양의 원을 감지 할 수있는 매개 변수 조합이 존재하지 않을 수도 있습니다. 다른 한편으로, 기본 투표 메커니즘으로 인해, "닫힌 (dent)"이있는 닫히지 않은 완전한 원 또는 완전한 원이 계속 나타날 수 있습니다. 따라서 예상 출력에 따라이 방법을 사용하거나 사용하지 않을 수도 있습니다.

즉,이 기능을 통해 내가 도울 수있는 몇 가지 사항이 있습니다.

  1. HoughCirclesCanny 내부적으로 전화를합니다. 그래서 당신은 그 전화를 끊을 수 있습니다.
  2. param1 (당신이 HIGH 라고 부름)은 전형적으로 200 의 값으로 초기화된다. 이것은 Canny 에 대한 내부 호출에 대한 매개 변수로 사용됩니다 : cv.Canny(processed, cannied, HIGH, HIGH/2) . 이처럼 Canny 직접 실행하면 Hough 설정이 Hough 변환에 사용 된 이미지에 어떻게 영향을 주는지 확인할 수 있습니다.
  3. param2 ( LOW )는 일반적으로 값 100 주위에서 초기화됩니다. Hough 변환의 누산기에 대한 투표 임계 값입니다. 이 값을 높게 설정하면 위양성이 많아지고 위양성이 낮아집니다. 나는 이것이 당신이 주변을 조롱하기 시작하려는 첫 번째 것이라고 믿습니다.

참고 : http://docs.opencv.org/3.0-beta/modules/imgproc/doc/feature_detection.html#houghcircles

업데이트 된 원 : 채워진 원 : Hough 변환을 사용하여 원 모양을 찾으면 경계 색을 샘플링하고이를 예상 원 안의 하나 이상의 점과 비교하여 채워지는지 테스트 할 수 있습니다. 또는 추정 원 안의 하나 이상의 점을 주어진 배경색과 비교할 수 있습니다. 이전 비교가 성공하면 원이 채워지고, 실패하면 대체 비교의 경우 원이 채워집니다.


다음은 비전 연구원으로서의 나의 경험을 바탕으로합니다. 귀하의 질문에서 당신은 가능한 알고리즘과 방법에 관심이있는 것 같습니다. 먼저 샘플 이미지를위한 빠르고 더러운 Python 스크립트를 제공하고 문제가 해결 될 수 있음을 입증하는 몇 가지 결과가 표시됩니다. 이러한 문제를 해결 한 후 강력한 탐지 알고리즘에 관한 귀하의 질문에 답변하려고 노력합니다.

빠른 결과

일부 샘플 이미지 (flickr.com에서 다운로드 한 이미지와 CC 라이센스가있는 모든 이미지)는 감지 된 서클과 함께 표시됩니다 (매개 변수를 변경 / 조정하지 않고 정확히 다음 코드를 사용하여 모든 이미지에서 원을 추출합니다).

코드 (MSER Blob Detector 기반)

그리고 여기 코드가 있습니다 :

import cv2
import math
import numpy as np

d_red = cv2.cv.RGB(150, 55, 65)
l_red = cv2.cv.RGB(250, 200, 200)

orig = cv2.imread("c.jpg")
img = orig.copy()
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

detector = cv2.FeatureDetector_create('MSER')
fs = detector.detect(img2)
fs.sort(key = lambda x: -x.size)

def supress(x):
        for f in fs:
                distx = f.pt[0] - x.pt[0]
                disty = f.pt[1] - x.pt[1]
                dist = math.sqrt(distx*distx + disty*disty)
                if (f.size > x.size) and (dist<f.size/2):
                        return True

sfs = [x for x in fs if not supress(x)]

for f in sfs:
        cv2.circle(img, (int(f.pt[0]), int(f.pt[1])), int(f.size/2), d_red, 2, cv2.CV_AA)
        cv2.circle(img, (int(f.pt[0]), int(f.pt[1])), int(f.size/2), l_red, 1, cv2.CV_AA)

h, w = orig.shape[:2]
vis = np.zeros((h, w*2+5), np.uint8)
vis = cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR)
vis[:h, :w] = orig
vis[:h, w+5:w*2+5] = img

cv2.imshow("image", vis)
cv2.imwrite("c_o.jpg", vis)
cv2.waitKey()
cv2.destroyAllWindows()

보시다시피 MSER 얼룩 검출기를 기반으로합니다. 이 코드는 그레이 스케일로의 단순 매핑과는 별도로 이미지를 전처리하지 않습니다. 따라서 이미지에서 희미한 노란색 얼룩을 놓치면됩니다.

이론

간단히 말해서, 문제에 대해 아는 것과는 별도로 설명이없는 단 두 개의 샘플 이미지 만 제공한다는 점을 제외하고는 알려주지 않습니다. 여기서 저는 왜 저의 겸손한 견해에서 문제를 공격 할 효율적인 방법이 무엇인지 질문하기 전에 문제에 대한 더 많은 정보를 얻는 것이 중요하다고 설명합니다.

주요 질문으로 돌아 가기 :이 문제에 가장 적합한 방법은 무엇입니까? 이것을 검색 문제로 보자. 토론을 단순화하기 위해 주어진 크기 / 반경으로 원을 찾고 있다고 가정합니다. 따라서 문제는 센터를 찾는 것으로 귀결됩니다. 모든 픽셀은 후보 센터이므로 검색 공간에는 모든 픽셀이 포함됩니다.

P = {p1, ..., pn} 
P: search space
p1...pn: pixels

이 검색 문제를 해결하려면 두 가지 다른 함수를 정의해야합니다.

E(P) : enumerates the search space
V(p) : checks whether the item/pixel has the desirable properties, the items passing the check are added to the output list

알고리즘의 복잡성이 중요하지 않다는 가정하에, E가 모든 픽셀을 취하여 V로 전달하는 철저한 검색을 사용할 수 있습니다. 실시간 응용 프로그램에서는 검색 공간을 줄이고 V의 계산 효율을 최적화하는 것이 중요합니다 .

우리는 주된 질문에 더 가까워지고 있습니다. 우리가 V를 어떻게 정의 할 수 있겠습니까? 후보자의 속성이 측정 값이어야하고 어떻게 바람직하고 바람직하지 않은지로 나누는 이분법 문제를 해결해야합니다. 가장 일반적인 접근법은 특성의 측정을 기반으로 간단한 의사 결정 규칙을 정의하는 데 사용할 수있는 일부 특성을 찾는 것입니다. 이것은 시행 착오로 당신이하고있는 일입니다. 긍정적이고 부정적인 예를 통해 학습함으로써 분류자를 프로그래밍하고 있습니다. 이것은 사용하고있는 방법이 당신이하고 싶은 것을 전혀 모르기 때문입니다. 결정 규칙의 매개 변수를 조정 / 조정하고 /하거나 이분법 문제에 대해이 방법에서 사용 된 속성 (원하는 후보의 특성)의 편차가 줄어들도록 데이터를 사전 처리해야합니다. 주어진 예제 세트에 대해 최적의 매개 변수 값을 찾기 위해 기계 학습 알고리즘을 사용할 수 있습니다. 의사 결정 나무에서부터 유전 공학에 이르기까지 다양한 알고리즘을 학습 할 수 있습니다. 또한 학습 알고리즘을 사용하여 여러 원 검출 알고리즘에 대한 최적의 매개 변수 값을 찾고 어느 것이 더 나은 정확도를 제공하는지 확인할 수 있습니다. 이것은 샘플 이미지를 수집하는 데 필요한 학습 알고리즘에 큰 부담이됩니다.

흔히 간과되는 강건성을 향상시키는 또 다른 방법은 추가로 쉽게 이용할 수있는 정보를 활용하는 것입니다. 거의 아무런 노력을하지 않고 서클의 색상을 알고 있다면 감지기의 정확성을 크게 향상시킬 수 있습니다. 비행기에서 원의 위치를 ​​알고 있고 이미징 된 원을 감지하고 싶다면이 두 위치 세트 간의 변환이 2D 호모 그래피로 설명되어야합니다. 그리고 homography는 4 점만을 사용하여 추정 할 수 있습니다. 그런 다음 견고성을 향상시켜 단단한 방법으로 만들 수 있습니다. 도메인 별 지식의 가치는 종종 과소 평가됩니다. 이 방법을 살펴보면, 첫 번째 접근법에서는 제한된 수의 샘플을 기반으로 일부 의사 결정 규칙을 근사하려고 시도합니다. 두 번째 접근법에서는 의사 결정 규칙을 알고 알고리즘에서 알고리즘을 효과적으로 활용할 수있는 방법을 찾아야합니다.

개요

요약하면 솔루션의 정확성 / 견고성을 향상시키는 데는 두 가지 접근 방식이 있습니다.

  1. 도구 기반 : 더 적은 수의 매개 변수로 알고리즘 사용 / 알고리즘 조정 / 기계 학습 알고리즘을 사용하여이 프로세스 자동화
  2. 정보 기반 : 쉽게 이용할 수있는 모든 정보를 사용하고 있습니까? 질문에서 당신은 당신이 그 문제에 대해 아는 것을 언급하지 않습니다.

공유 한 두 이미지의 경우 HT 방법이 아닌 얼룩 검출기를 사용합니다. 배경 뺄셈을 위해서 나는 원의 색이 변화하는 동안 변화가없는 두 이미지에서와 같이 배경색을 추정하려고 시도 할 것을 제안합니다. 그리고 대부분의 지역은 맨손입니다.


이것은 훌륭한 모델링 문제입니다. 나는 다음의 추천 / 아이디어를 가지고있다 :

  1. 이미지를 RGB로 분할 한 다음 처리하십시오.
  2. 사전 처리.
  3. 동적 매개 변수 검색.
  4. 제약 조건을 추가하십시오.
  5. 당신이 탐지하려고 시도하고있는 것을 확실하게하십시오.

더 자세하게:

1 : 다른 답변에서 언급했듯이, 회색 음영으로 변환하면 너무 많은 정보가 삭제되므로 배경과 비슷한 밝기의 원은 모두 손실됩니다. 색상 채널을 격리되어 있거나 다른 색상 공간에서 고려하는 것이 훨씬 좋습니다. 여기에는 거의 두 가지 방법이 있습니다 : HoughCircles 된 각 채널에서 HoughCirclesHoughCircles 으로 수행 한 다음 결과를 결합하거나 채널을 처리 한 다음 결합하여 HoughCircles 를 조작 HoughCircles . 아래의 제 시도에서 두 번째 방법을 시도했습니다. RGB 채널로 분할하고 처리 한 다음 결합합니다. 결합 할 때 이미지를 포화시키는 것에주의하십시오.이 이미지를 사용하지 cv.And 려면이 단계를 사용하십시오.이 단계에서 내 서클은 항상 흰색 배경에 검은 색 고리 / 디스크입니다.

2 : 전처리는 매우 까다 롭습니다. AdaptiveThreshold 는 로컬 평균을 기준으로 픽셀을 임계 값으로 설정하여 이미지의 가장자리를 향상시킬 수있는 강력한 회선 방법입니다 (유사한 프로세스가 포유류 시각 시스템의 초기 경로에서도 발생 함). 이것은 약간의 잡음을 줄이기 때문에 유용합니다. 나는 단 한 번의 통과로 dilate/erode 을 사용했습니다. 그리고 나는 다른 매개 변수를 어떻게 유지했는지 알았습니다. HoughCircles 가 '채워진 원'을 찾는 데 많은 도움이되기 전에 Canny 를 사용하는 것 같습니다.이 사전 처리는 상당히 무겁고 다소 더 많은 'blobby circle'을 포함하는 오 탐지로 이어질 수 있지만, 우리의 경우 이것은 아마도 바람직 할 것인가?

3 : 최적의 솔루션을 얻으려면 각 이미지에 대해 HoughCircles 매개 변수 param2 (매개 변수 LOW )를 조정해야합니다. 실제로는 docs 에서 확인하십시오.

크기가 작을수록 더 많은 거짓 서클이 감지 될 수 있습니다.

문제는 모든 이미지에서 달콤한 부분이 달라질 것입니다. 여기서 가장 좋은 방법은 조건을 설정하고이 조건이 충족 될 때까지 다른 param2 값을 검색하는 것입니다. 이미지에 중첩되지 않는 서클이 표시되며 param2 가 너무 낮 으면 일반적으로 겹치는 서클이 많이 param2 . 그래서 나는 다음을 찾도록 제안한다 :

비 중첩 및 포함되지 않은 서클의 최대 수

그래서 우리는 이것이 충족 될 때까지 param2 값이 다른 HoughCircles를 계속 호출합니다. 아래 예제에서 param2 임계 값 가정에 도달 할 때까지 증가시킵니다. 이것이 언제 충족되는지를 찾기 위해서 바이너리 검색을 수행하는 것이 더 빠르며 (그리고 상당히 쉽다), opencv는 종종 무해한 param2 값을위한 에러를 throw하기 때문에 예외 처리에주의를 기울여야한다. 내 설치). 일치하는 데 매우 유용한 다른 조건은 서클의 수입니다.

4 : 모델에 추가 할 수있는 제약이 더 있습니까? 우리가 우리 모델에 서클을 탐지하기 위해 할 수있는 일을 쉽게 말할 수있는 물건이 많을수록. 예를 들어, 우리는 다음을 알고 있습니까?

  • 서클의 수입니다. - 상한선 또는 하한선이 도움이됩니다.
  • 원 또는 배경 또는 '비 원'의 가능한 색상입니다.
  • 그들의 크기.
  • 그들이 이미지에있을 수있는 곳.

5 : 이미지의 얼룩 중 일부는 느슨하게 동그라미라고 할 수 있습니다! 두 번째 이미지에서 두 개의 '원형이 아닌 얼룩 (blob)'을 생각해 보겠습니다. 코드에서 찾을 수 없습니다 (좋음). 그러나 ... 포토샵을 사용하면 더 원형이되고, 코드에서 찾을 수 있습니다. 어쩌면 원이 아닌 것을 탐지하고 싶다면 Tim Lukins 와 같은 다른 접근법이 더 좋을 수 있습니다.

문제들

무거운 전처리 AdaptiveThresholding 과`Canny '를 수행함으로써 이미지의 특징에 많은 왜곡이 생길 수 있습니다. 이로 인해 잘못된 서클 감지 또는 잘못된 반경보고가 발생할 수 있습니다. 예를 들어 처리 후 대형 솔리드 디스크가 링으로 나타날 수 있으므로 HughesCircles에서 내부 링을 찾을 수 있습니다. 심지어 문서는 다음과 같이 기록합니다.

... 일반적으로이 함수는 원의 중심을 잘 감지하지만 올바른 반경을 찾지 못할 수 있습니다.

보다 정확한 반지름 감지가 필요하면 다음 방법을 제안합니다 (구현되지 않음).

  • 원본 이미지에서 확대 된 교차점 (4 개의 광선 : 위 / 아래 / 왼쪽 / 오른쪽)에서보고 된 원 중심에서의 광선 추적
  • 각 RGB 채널에서이 작업을 별도로 수행하십시오.
  • 현명한 방식으로 각 광선의 각 채널에 대해이 정보를 결합하십시오 (즉, 필요에 따라 뒤집기, 오프셋, 크기 조절 등)
  • 각 광선의 처음 몇 픽셀에 대해 평균을 취하고 광선의 중요한 편차가 발생하는 곳을 감지하려면이 값을 사용하십시오.
  • 이 4 점은 둘레의 점을 추정 한 것입니다.
  • 이 네 가지 추정치를 사용하여보다 정확한 반지름과 중심 위치 (!)를 결정하십시오.
  • 이것은 네 개의 광선 대신 확장 고리를 사용하여 일반화 할 수 있습니다.

결과

끝에있는 코드는 꽤 좋은 시간을 꽤 많이줍니다.이 예제는 다음과 같이 코드로 수행되었습니다.

첫 번째 이미지의 모든 서클을 감지합니다.

캐니 필터 (canny filter)가 적용되기 전에 사전 처리 된 이미지가 어떻게 보이는지 (다른 색 원이 크게 보임) :

두 번째 이미지에서 두 개 (방울)를 제외한 모든 것을 감지합니다.

변경된 두 번째 이미지 (얼룩이 원형으로 흐려지고 큰 타원형이 원형으로 만들어 감지가 향상됨)

이 Kandinsky 그림 (나는 경계 조건 때문에 동심원 고리를 찾을 수 없음)의 중심을 탐지하는데 꽤 잘 맞 읍니다.

암호:

import cv
import numpy as np

output = cv.LoadImage('case1.jpg')
orig = cv.LoadImage('case1.jpg')

# create tmp images
rrr=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
ggg=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
bbb=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
processed = cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)

def channel_processing(channel):
    pass
    cv.AdaptiveThreshold(channel, channel, 255, adaptive_method=cv.CV_ADAPTIVE_THRESH_MEAN_C, thresholdType=cv.CV_THRESH_BINARY, blockSize=55, param1=7)
    #mop up the dirt
    cv.Dilate(channel, channel, None, 1)
    cv.Erode(channel, channel, None, 1)

def inter_centre_distance(x1,y1,x2,y2):
    return ((x1-x2)**2 + (y1-y2)**2)**0.5

def colliding_circles(circles):
    for index1, circle1 in enumerate(circles):
        for circle2 in circles[index1+1:]:
            x1, y1, Radius1 = circle1[0]
            x2, y2, Radius2 = circle2[0]
            #collision or containment:
            if inter_centre_distance(x1,y1,x2,y2) < Radius1 + Radius2:
                return True

def find_circles(processed, storage, LOW):
    try:
        cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 32.0, 30, LOW)#, 0, 100) great to add circle constraint sizes.
    except:
        LOW += 1
        print 'try'
        find_circles(processed, storage, LOW)
    circles = np.asarray(storage)
    print 'number of circles:', len(circles)
    if colliding_circles(circles):
        LOW += 1
        storage = find_circles(processed, storage, LOW)
    print 'c', LOW
    return storage

def draw_circles(storage, output):
    circles = np.asarray(storage)
    print len(circles), 'circles found'
    for circle in circles:
        Radius, x, y = int(circle[0][2]), int(circle[0][0]), int(circle[0][1])
        cv.Circle(output, (x, y), 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
        cv.Circle(output, (x, y), Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

#split image into RGB components
cv.Split(orig,rrr,ggg,bbb,None)
#process each component
channel_processing(rrr)
channel_processing(ggg)
channel_processing(bbb)
#combine images using logical 'And' to avoid saturation
cv.And(rrr, ggg, rrr)
cv.And(rrr, bbb, processed)
cv.ShowImage('before canny', processed)
# cv.SaveImage('case3_processed.jpg',processed)
#use canny, as HoughCircles seems to prefer ring like circles to filled ones.
cv.Canny(processed, processed, 5, 70, 3)
#smooth to reduce noise a bit more
cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 7, 7)
cv.ShowImage('processed', processed)
#find circles, with parameter search
storage = find_circles(processed, storage, 100)
draw_circles(storage, output)
# show images
cv.ShowImage("original with circles", output)
cv.SaveImage('case1.jpg',output)

cv.WaitKey(0)

좋아, 이미지를보고. **Active Contours** 사용을 권장합니다.

  • 활성 윤곽 활성 윤곽에 대한 좋은 점은 어떤 주어진 모양에도 거의 완벽하게 들어 맞습니다. 정사각형이나 삼각형이어야하며 귀하의 경우에는 완벽한 후보자가되어야합니다.
  • 원의 중심을 추출 할 수 있다면 좋습니다. 활성 윤곽선은 항상 시작점을 지정해야합니다. 시작점부터 시작하여 점차 커지거나 축소 될 수 있습니다. 센터가 항상 센터에 정렬 될 필요는 없습니다. 약간의 오프셋은 여전히 ​​괜찮을 것입니다.
  • 그리고 당신의 경우에 윤곽선이 중심에서 바깥쪽으로 자라게한다면, 그들은 원의 경계를 쉬게됩니다.
  • 확대 또는 축소되는 활성 윤곽선은 풍선 에너지 를 사용하므로 윤곽선, 안쪽 또는 바깥 쪽 방향을 설정할 수 있습니다.
  • 아마도 그레이 스케일로 그래디언트 이미지를 사용해야 할 것입니다. 그러나 여전히 색상으로 시도 할 수 있습니다. 작동한다면!
  • 그리고 센터를 제공하지 않으면 많은 액티브 컨투어를 버리고 성장시키고 축소하십시오. 안정된 컨투어는 유지되고, 불안정한 컨투어는 버려집니다. 이것은 무차별 적 접근입니다. CPU 사용률이 높을 것입니다. 그러나 올바른 윤곽선을 남기고 나쁜 윤곽선을 버리기 위해보다 신중한 작업이 필요합니다.

나는 당신이 문제를 해결할 수 있기를 희망합니다.





computer-vision