sourcecode

OpenCV(Hough 변환 또는 기타 기능에 기반)를 사용한 견고한(색상과 크기 불변) 원 검출 쓰기

copyscript 2022. 8. 9. 22:53
반응형

OpenCV(Hough 변환 또는 기타 기능에 기반)를 사용한 견고한(색상과 크기 불변) 원 검출 쓰기

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

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:

입력 1 검출 1 사후 처리 1

케이스 2:

입력 2 검출 2 사후 처리 2

Case1과 Case2는 기본적으로 동일한 이미지이지만 알고리즘은 다른 원을 검출합니다.알고리즘에 크기가 다른 원의 이미지를 제시하면 원 검출이 완전히 실패할 수도 있습니다. '아예'에 의한 것입니다.HIGH ★★★★★★★★★★★★★★★★★」LOW각 새 사진에 대해 개별적으로 조정해야 하는 파라미터.

그래서 내 질문은:이 알고리즘을 보다 견고하게 하기 위한 다양한 가능성은 무엇입니까?색상과 크기가 서로 다른 원이 검출되도록 크기와 색상이 일정하지 않아야 합니다.Hough 트랜스폼을 사용하는 것이 최선의 방법이 아닐까요?더 나은 방법이 있을까요?

다음은 저의 비전 연구자 경험을 바탕으로 한 것입니다.당신의 질문에서 당신은 코드 조각보다는 가능한 알고리즘과 메서드에 관심이 있는 것 같습니다.먼저 샘플 이미지를 위한 빠르고 더러운 Python 스크립트를 제공하고 몇 가지 결과를 통해 문제를 해결할 수 있음을 알 수 있습니다.이것들을 제거한 후, 저는 강력한 검출 알고리즘에 대한 당신의 질문에 답하려고 합니다.

빠른 결과

일부 샘플 이미지(사용하는 이미지 이외의 모든 이미지는 flickr.com에서 다운로드되며 CC 라이센스가 부여됨)는 검출된 원(파라미터를 변경하거나 조정하지 않고 정확히 다음 코드를 사용하여 모든 이미지에서 원을 추출합니다). 샘플 이미지 1에서 탐지된 블럽 검체 이미지에서 탐지된 블럽 2 많은 원들 플리커 이미지 1의 블러

코드(MSER Blob 디텍터에 기반)

코드는 다음과 같습니다.

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 블롭 디텍터를 기반으로 합니다.이 코드는 그레이스케일로의 간단한 매핑을 제외하고 이미지를 사전 처리하지 않습니다.따라서 이미지에서 희미한 노란색 얼룩이 사라집니다.

이론.

요컨대, 문제에 대해 알고 있는 것은 설명 없이 샘플 이미지 2개만 제공하는 것 이외에는 말하지 않습니다.여기에서는 문제를 해결하기 위한 효과적인 방법이 무엇인지 묻기 전에 문제에 대해 더 많은 정보를 얻는 것이 중요하다고 생각하는 이유를 설명합니다.

주요 질문으로 돌아가겠습니다.이 문제에 가장 적합한 방법은 무엇입니까?이 문제를 검색 문제로 살펴보겠습니다.논의를 단순화하기 위해 주어진 크기/반경을 가진 원을 찾고 있다고 가정합니다.따라서 문제는 결국 센터를 찾는 것이다.모든 화소가 후보 중심이기 때문에 서치 공간에는 모든 화소가 포함됩니다.

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 호모그래피로 설명되어 있습니다.그리고 호모그래피는 4점만으로 추정할 수 있습니다.그런 다음 견고성을 향상시켜 견고한 방법을 사용할 수 있습니다.도메인 고유의 지식의 가치는 종종 과소평가됩니다.이렇게 보면, 첫 번째 접근법에서는 제한된 수의 샘플을 바탕으로 몇 가지 의사결정 규칙을 근사화하려고 합니다.두 번째 접근법에서는 의사결정 규칙을 알고 있으며 알고리즘에서 의사결정 규칙을 효과적으로 활용할 수 있는 방법만 찾으면 됩니다.

요약

요약하면 솔루션의 정확성/강건성을 개선하기 위한 두 가지 접근법이 있습니다.

  1. 도구 기반: 보다 사용하기 쉬운 알고리즘 찾기/파라미터 수 감소/알고리즘 조정/기계학습 알고리즘을 사용한 프로세스 자동화
  2. 정보 기반: 즉시 사용할 수 있는 모든 정보를 사용하고 있습니까?질문에서는 문제에 대해 알고 있는 것을 언급하지 않습니다.

당신이 공유한 이 두 이미지에는 HT 방식이 아닌 BLOB 디텍터를 사용합니다.배경 감산은 두 이미지에서 배경색이 변하지 않고 원의 색이 다르기 때문에 배경색을 추정해 보는 것이 좋습니다.그리고 대부분의 지역이 비어있습니다.

이것은 훌륭한 모델링 문제입니다.다음과 같은 권장사항/아이디어가 있습니다.

  1. 이미지를 RGB로 분할하여 처리한다.
  2. 전처리
  3. 동적 파라미터 검색
  4. 구속조건을 추가합니다.
  5. 검출하려고 하는 것을 확인해 주세요.

상세:

1: 다른 답변에서 언급했듯이 그레이스케일로 직접 변환하면 너무 많은 정보가 손실됩니다. 이치노많이 격리 또는 다른 색상 공간에서 색상 채널을 고려하는 것이 좋다.가는 은 크게 두. 즉, 수행 방법이 있습니다.HoughCircles프리패키지', '프리패키지', '프리패키지', '프리패키지', '프리패키지', '프리패키지', '프리패키지', '프리패키지', '프리패키지', '프리패키지', '프리패키지'를 조작합니다.HoughCircles하는 두 방법을 내 시도 아래에서, 나는, RGB채널, 가공, 그 결합하기 위해 나뉘어 지며 두번째 대안을 시도해 봤다.때 하게 포화되지 .cv.And(이 단계에서 하얀 배경에 내 서클은 항상 검은 rings/discs)이 문제를 피하기 위해.

까다롭기 노는 .2: 전처리 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」나는을 사용했어요AdaptiveThreshold이미지에 픽셀들은 지역 평균(유사한 과정 또한 포유류의 시각 체계의 빠른 경로에서 발생하는)에 기초한 경계화에 의해 가장자리를 향상시킬 수 있는 정말 강력한 꼬임 선 방법이다.얼마간의 소음을 감소시킨다 이 또한 유용하다.dilate/erode오직 한번 지나가면서.그리고 나는 어떻게 이 사람은 다른 파라미터들 유지해 왔습니다.그것은 사용하는 것 같Canny 전에HoughCircles'동그라미를 찾는 데 도움이 것이 채운 동그라미'를 찾는 데 많은 도움이 되므로 계속 넣어두는 것이 좋습니다.이 전처리는 상당히 무겁고 다소 더 '귀한 서클'이 있는 잘못된 양성으로 이어질 수 있지만, 우리의 경우 이것이 바람직할까요?

3: " " " " " " HoughCircles " " "param2( 「」)LOW최적의 솔루션을 얻으려면 각 이미지에 대해 조정해야 합니다.실제로 다음 문서를 참조해 주십시오.

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

문제는 모든 이미지에 따라 스위트 스팟이 다르다는 것입니다.은 조건을 정하고 검색어를 통해서 합니다.param2이 조건이 충족될 때까지 값을 지정합니다. 않는 원이 표시되며, 겹치지 않는 원이 됩니다.param2일반적으로 겹치는 원의 하중이 너무 낮습니다.라음

비연결 및 비포함 원의 최대 수

HoughCircles 값이 호출하고 .param2이 조건이 충족될 때까지요.에서는 이 을 단순히 시키면 됩니다.param2문턱값 가정에 도달할 때까지요.하여 이 충족되는 것이 쉽게 할 수 있습니다).단, .param2동그라미 수와의 합니다.우리가 비교할 수 있는 다른 조건은 원의 수일 것입니다.

4: 모델에 추가할 수 있는 제약사항이 있습니까?모델에게 더 많은 정보를 전달할수록 원을 탐지하는 작업이 쉬워집니다.예를 들어 다음과 같습니다.

  • 원의 수 - 상한 또는 하한도 유용합니다.
  • 원, 배경 또는 '비원'의 가능한 색상.
  • 사이즈.
  • 이미지 안에 있을 수 있는 곳.

수 ! 5: 이미지에 있는 일부 얼룩은 대략적으로 원이라고 불릴 수 밖에 없습니다!두 번째 이미지에서 두 개의 '비원형 블럽'을 생각해 보십시오. 내 코드는 찾을 수 없습니다(좋습니다!). 찾을 수 ...만약 이 원이, 예를 들어 원과 같이 수 있습니다.Tim Lukins더 나을지도 몰라

문제

전처리를 AdaptiveThresholding 「, 검출이나 리포트로 .예를 들어 처리 후 대형 솔리드 디스크가 링처럼 보일 수 있으므로 HughesCircles는 내부 링을 찾을 수 있습니다.게다가 다음의 점에 대해서는, 문서도 주의해 주세요.

...보통 이 기능은 원의 중심을 잘 감지하지만 정확한 반지름을 찾지 못할 수 있습니다.

보다 정확한 반지름 검출이 필요한 경우 다음 접근법(실장되지 않음)을 권장합니다.

  • 원본 이미지에서 보고된 원의 중심으로부터의 광선 트레이스(확장 십자선 4개: 위/아래/왼쪽/오른쪽)
  • 각 RGB 채널에서 개별적으로 실행
  • 각 광선의 각 채널에 대해 적절한 방식으로 이 정보를 결합합니다(즉, 필요에 따라 플립, 오프셋, 스케일 등).
  • 각 광선의 처음 몇 픽셀에 대한 평균을 구합니다. 이 평균을 사용하여 광선의 중요한 편차가 발생하는 위치를 탐지합니다.
  • 이 4개의 점은 원주상의 점의 추정치입니다.
  • 이 4개의 추정치를 사용하여 보다 정확한 반지름과 중심 위치(!)를 결정합니다.
  • 이는 4개의 광선 대신 확장 링을 사용하여 일반화할 수 있다.

결과.

대부분의 경우 이 코드는 매우 잘 동작합니다.다음 예시는 다음과 같이 코드를 사용하여 수행되었습니다.

이미지에서 합니다.여기에 이미지 설명 입력

캐니 필터를 적용하기 전에 사전 처리된 이미지의 모양(다른 색상의 원이 매우 잘 보입니다):여기에 이미지 설명 입력

에서 두 개 의 모든 (합니다.여기에 이미지 설명 입력

의 화상되어 큰 원형으로 검출이 은검출됩니다.여기에 이미지 설명 입력

이 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)

아, 네... 원 문제에 대한 오래된 색상/크기 불변량(일명 Hough 변환은 너무 구체적이고 견고하지 않음)...

저는 과거에 OpenCV의 구조형상 분석 기능에 훨씬 더 의존했습니다.가능한 것에 대한 매우 좋은 아이디어는 "샘플" 폴더에서 얻을 수 있습니다 - 특히fitellipse.py ★★★★★★★★★★★★★★★★★」squares.py.

설명을 위해, 저는 당신의 원래 출처를 바탕으로 이 예들의 하이브리드 버전을 제시합니다.탐지된 등고선은 녹색으로 표시되고 적합 타원형은 빨간색으로 표시됩니다.

여기에 이미지 설명 입력

아직 그 정도는 아닙니다.

  • 더 희미한 원을 감지하려면 전처리 단계를 약간 조정해야 합니다.
  • 등고선을 추가로 검정하여 원인지 여부를 확인할 수 있습니다.

행운을 빕니다.

import cv
import numpy as np

# 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)
storage = cv.CreateMemStorage(0)

contours = cv.FindContours(processed, storage, cv.CV_RETR_EXTERNAL)
# N.B. 'processed' image is modified by this!

#contours = cv.ApproxPoly (contours, storage, cv.CV_POLY_APPROX_DP, 3, 1) 
# If you wanted to reduce the number of points...

cv.DrawContours (orig, contours, cv.RGB(0,255,0), cv.RGB(255,0,0), 2, 3, cv.CV_AA, (0, 0)) 

def contour_iterator(contour):
  while contour:
    yield contour
    contour = contour.h_next()

for c in contour_iterator(contours):
  # Number of points must be more than or equal to 6 for cv.FitEllipse2
  if len(c) >= 6:
    # Copy the contour into an array of (x,y)s
    PointArray2D32f = cv.CreateMat(1, len(c), cv.CV_32FC2)

    for (i, (x, y)) in enumerate(c):
      PointArray2D32f[0, i] = (x, y)

    # Fits ellipse to current contour.
    (center, size, angle) = cv.FitEllipse2(PointArray2D32f)

    # Convert ellipse data from float to integer representation.
    center = (cv.Round(center[0]), cv.Round(center[1]))
    size = (cv.Round(size[0] * 0.5), cv.Round(size[1] * 0.5))

    # Draw ellipse
    cv.Ellipse(orig, center, size, angle, 0, 360, cv.RGB(255,0,0), 2,cv.CV_AA, 0)

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

편집:

이 모든 답변에 대한 주요 테마가 있다고 생각되는 업데이트는 당신이 원형으로 인식하고자 하는 것에 적용할 수 있는 많은 추가 가정과 제약이 있다는 것입니다.저 자신의 답변은 낮은 수준의 전처리도 높은 수준의 기하학적 피팅도 아닌, 이 점에 대해 아무런 언급도 하지 않았습니다.대부분의 원이 그리거나 이미지의 비아핀/투영 변환 및 렌더링/캡처 방법(컬러, 노이즈, 조명, 가장자리 두께)에 따라 실제로는 그렇게 둥글지 않다는 사실은 모두 하나의 이미지 내에서 가능한 여러 개의 원 후보가 됩니다.

훨씬 더 정교한 기술들이 있다.하지만 대가를 치르게 될 거야개인적으로 저는 @fraxel의 부가 임계값을 사용하는 아이디어를 좋아합니다.그것은 빠르고 신뢰성이 높으며 상당히 견고합니다.그런 다음 최종 윤곽선(예: Hu 모멘트 사용) 또는 부속품을 타원 축의 단순 비율 테스트로 추가로 테스트할 수 있습니다(예: (min(size)/max(size)> 0.7).

컴퓨터 비전과 마찬가지로 실용주의, 원리, 파소모니 사이에는 긴장감이 존재한다.나는 CV가 쉽다고 생각하는 사람들에게 말하는 것을 좋아하기 때문에 그렇지 않다. 사실 그것은 AI의 완전한 문제로 유명하다.이 밖에도 종종 기대할 수 있는 최선은 대부분의 시간 동안 효과가 있는 것입니다.

당신의 코드를 살펴본 결과, 다음과 같은 것이 있었습니다.

  • 그레이스케일 변환당신이 왜 그렇게 하는지 이해하지만, 당신이 거기에 정보를 버리고 있다는 것을 깨달으세요."후 처리" 이미지에서 볼 수 있듯이 노란색 동그라미는 배경과 동일한 강도로 다른 색상으로 표시됩니다.

  • 노이즈 제거 후 에지 감지(삭제/희석)그럴 필요 없어요. 캐니가 알아서 해야죠.

  • 캐니 에지 검출"열린" 원에는 안쪽 가장자리와 바깥쪽 가장자리가 있습니다.꽤 가깝기 때문에 Canny Gauss 필터가 둘을 합칠 수 있습니다.그렇지 않으면 두 개의 가장자리가 서로 가까워질 것입니다.즉, Canny 이전에는 열린 원과 채워진 원이 있습니다.그 후에는 각각 0/2와 1의 가장자리가 됩니다.Hough가 Canny를 다시 호출하기 때문에 첫 번째 경우 두 에지가 함께 평활될 수 있습니다(초기 폭에 따라 다름). 따라서 코어 Hough 알고리즘은 열린 원과 채워진 원을 동일하게 취급할 수 있습니다.

첫 번째 권장 사항은 그레이스케일 매핑을 변경하는 것입니다.강도를 사용하지 말고 색상/채도/값을 사용하십시오.또한, 가장자리를 찾고 있는 차동적 접근 방식을 사용하십시오.계산해 .HSV변환하고 복사본을 평활화한 다음 원본 복사본과 평활 복사본의 차이를 가져옵니다.으로 끝이다dH, dS, dV( Hue , Saturation , Value ) 。정사각형을 더하면 모든 가장자리(내부 및 외부) 근처에 피크가 있는 1차원 이미지를 얻을 수 있습니다.

두 번째 추천은 국지적 정상화입니다만, 그것이 필요한지는 잘 모르겠습니다.출력한 에지 신호의 정확한 값은 특별히 신경 쓰지 않고 실제로는 이진수여야 합니다(에지 여부에 관계없이).따라서 로컬 평균(로컬이 에지 크기 순서)으로 나누어 각 값을 정규화할 수 있습니다.

Hough 변환은 "모델"을 사용하여 (일반적으로) 에지 감지 이미지에서 특정 피쳐를 찾습니다. HoughCircles그 모델은 완벽한 원이다.즉, 잘못된 긍정의 수를 늘리지 않고도 사진에서 더 불규칙한 원과 타원 모양의 원을 탐지할 수 있는 매개 변수의 조합은 존재하지 않을 수 있습니다.반면, 기초적인 투표 메커니즘으로 인해 닫힌 완전원 또는 덴트가 있는 완전원이 일관되게 나타날 수 있다.따라서 예상되는 출력에 따라 이 방법을 사용할 수도 있고 사용하지 않을 수도 있습니다.

단, 이 기능을 사용하는 데 도움이 될 수 있는 몇 가지 사항이 있습니다.

  1. HoughCircles ®Canny네, 네, 네, 네.
  2. param1이 그것을 (그것은)라고 부릅니다.HIGH은, , 의 됩니다.200는 내부 Cannycv.Canny(processed, cannied, HIGH, HIGH/2) 「 」를 실행하는 것이 이 될 수 .Canny ' 정도'를 설정했는지 하겠습니다.HIGH허우적거리다
  3. param2이 그것을 (그것은)라고 부릅니다.LOW으로 값 됩니다. 는 、 는 、 는 、 ) 、 ) ) ) ) ) ) ) ) ) ) ) ) 。100Hough 트랜스폼의 어큐뮬레이터에 대한 투표 문턱값입니다.더 높게 설정하면 더 많은 잘못된 부정, 더 적은 양의 잘못된 긍정입니다.만지작거리고 싶은 건 이게 처음이라고 생각해요.

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

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

츠요시사용하는 것을 추천합니다.**Active Contours**

  • 활성 등고선 활성 등고선의 장점은 주어진 모양에 거의 완벽하게 들어맞는다는 것입니다.정사각형이든 삼각형이든 당신의 경우 그들은 완벽한 후보입니다.
  • 만약 당신이 원의 중심을 추출할 수 있다면, 그것은 훌륭합니다.활성 등고선은 항상 적합하도록 확장하거나 축소할 수 있는 시작점이 필요합니다.중심이 항상 중심에 맞춰져 있을 필요는 없습니다.약간의 오프셋은 여전히 괜찮습니다.
  • 그리고 당신의 경우, 등고선이 중심에서 바깥쪽으로 자라도록 놔두면, 그들은 원의 경계를 유지하게 될 것이다.
  • 증가하거나 축소되는 활성 등고선은 풍선 에너지를 사용합니다. 즉, 등고선의 방향을 안쪽 또는 바깥쪽으로 설정할 수 있습니다.
  • 그레이스케일의 그라데이션 이미지를 사용해야 할 수도 있습니다.하지만 컬러도 시도해 볼 수 있습니다.잘 되면!
  • 센터를 제공하지 않으면 활성 등고선을 많이 삽입한 후 확장/축소합니다.정착한 윤곽은 유지되고, 불안정한 윤곽은 버려집니다.이것은 무차별적인 접근법입니다.CPU 부하가 높아집니다.하지만 올바른 윤곽을 남기고 나쁜 윤곽을 없애려면 더 세심한 작업이 필요합니다.

이렇게 하면 문제를 해결할 수 있을 거예요.

언급URL : https://stackoverflow.com/questions/9860667/writing-robust-color-and-size-invariant-circle-detection-with-opencv-based-on

반응형