๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

AI/Computer Vision

[Computer Vision] ๊ฐ์ฒด ๊ฒ€์ถœ๊ณผ ์‘์šฉ

728x90
๋ฐ˜์‘ํ˜•
๐Ÿ‘€ ๋ณธ ์˜ˆ์ œ๋Š” Window10์˜ VSCode, Python3.11.0๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

๊ฐ์ฒด ๊ฒ€์ถœ(Object Detecting)

์ž…๋ ฅ ์˜์ƒ์—์„œ ์ž‘์€ ํฌ๊ธฐ์˜ ๋ถ€๋ถ„ ์˜์ƒ์„ ์œ„์น˜๋ฅผ ์ฐพ์•„ ๋‚ด๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ํ…œํ”Œ๋ฆฟ ๋งค์นญ(Template Matching) ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค.

 

ํ…œํ”Œ๋ฆฟ์€ ์ฐพ๊ณ ์ž ํ•˜๋Š” ๋Œ€์ƒ์ด ๋˜๋Š” ์ž‘์€ ํฌ๊ธฐ์˜ ์˜์ƒ์„ ์˜๋ฏธํ•œ๋‹ค.

 

ํ…œํ”Œ๋ฆฟ ๋งค์นญ์€ ์ด ํ…œํ”Œ๋ฆฟ์„ ์ž…๋ ฅ ์˜์ƒ ์ „์ฒด ์˜์—ญ์— ๋Œ€ํ•ด ์ด๋™ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ๋น„์Šทํ•œ ์œ„์น˜๋ฅผ ์ˆ˜์ง์ ์œผ๋กœ ์ฐพ์•„๋‚ด๋Š” ๋ฐฉ์‹์ด๋‹ค.

  • ์œ ์‚ฌํ•œ ๊ฒƒ์„ ์ฐพ๋Š” ๋ฐฉ์‹์€ ํ…œํ”Œ๋ฆฟ๊ณผ ์ž…๋ ฅ ์˜์ƒ๊ฐ„์˜ ์œ ์‚ฌ๋„(Similarity) ๋˜๋Š” ๋น„์œ ์‚ฌ๋„(Dissimilarity)๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค. 
  • ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ : ํ…œํ”Œ๋ฆฟ ์˜์ƒ๊ณผ ๋น„์Šทํ•œ ๋ถ€๋ถ„ ์˜์ƒ ์œ„์น˜์—์„œ ๊ฐ’์ด ํฌ๊ฒŒ ๋‚˜ํƒ€๋‚จ.
  • ๋น„์œ ์‚ฌ๋„ ๊ณ„์‚ฐ : ํ…œํ”Œ๋ฆฟ ์˜์ƒ๊ณผ ๋น„์Šทํ•œ ๋ถ€๋ถ„์—์„œ ๊ฐ’์ด ์ž‘๊ฒŒ ๋‚˜ํƒ€๋‚จ.

 

import cv2

image = cv2.imread("test.png")
image = cv2.resize(image,(int(image.shape[1]//2),int(image.shape[0]//2)),interpolation=cv2.INTER_LANCZOS4)
template = cv2.imread("template.png")
template = cv2.resize(template,(int(template.shape[1]//2),int(template.shape[0]//2)),interpolation=cv2.INTER_LANCZOS4)
h,w,_ = template.shape


# Template Matching
result = cv2.matchTemplate(image,template,cv2.TM_CCOEFF_NORMED)
# TM_CCOEFF: ์ƒ๊ด€ ๊ณ„์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งค์นญ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ’์ด ํด์ˆ˜๋ก ๋งค์นญ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
# TM_CCOEFF_NORMED: ์ •๊ทœํ™”๋œ ์ƒ๊ด€ ๊ณ„์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ ๊ฐ’์€ 0๊ณผ 1 ์‚ฌ์ด๋กœ, 1์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ๋งค์นญ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
# TM_CCORR: ์ƒ๊ด€์„ ์‚ฌ์šฉํ•˜์—ฌ ๋งค์นญํ•ฉ๋‹ˆ๋‹ค. ๊ฐ’์ด ํด์ˆ˜๋ก ๋งค์นญ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
# TM_CCORR_NORMED: ์ •๊ทœํ™”๋œ ์ƒ๊ด€์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ ๊ฐ’์€ 0๊ณผ 1 ์‚ฌ์ด์ž…๋‹ˆ๋‹ค.
# TM_SQDIFF: ์ œ๊ณฑ ์ฐจ์ด๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๋งค์นญํ•ฉ๋‹ˆ๋‹ค. ๊ฐ’์ด ์ž‘์„์ˆ˜๋ก ๋งค์นญ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
# TM_SQDIFF_NORMED: ์ •๊ทœํ™”๋œ ์ œ๊ณฑ ์ฐจ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ ๊ฐ’์€ 0๊ณผ 1 ์‚ฌ์ด๋กœ, 0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ๋งค์นญ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

# ๋งค์นญ ๊ฒฐ๊ณผ์—์„œ ์ตœ๋Œ“๊ฐ’๊ณผ ์œ„์น˜๋ฅผ ์ฐพ๋Š”๋‹ค.
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

# ํ…œํ”Œ๋ฆฟ์˜ ์œ„์น˜๋ฅผ ์‚ฌ๊ฐํ˜•์œผ๋กœ ๊ทธ๋ฆฐ๋‹ค.
top_left = max_loc
bottom_right = (top_left[0]+w,top_left[1]+h)
cv2.rectangle(image,top_left,bottom_right,(0,255,0),2)

cv2.imshow("Template",template)
cv2.imshow("Template Matching",image)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

ํ…œํ”Œ๋ฆฟ ๋งค์นญ ๋น„๊ต ๋ฐฉ์‹ ๋ฉ”์†Œ๋“œ

  • TM_CCOEFF: ์ƒ๊ด€ ๊ณ„์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งค์นญ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ๊ฐ’์ด ํด์ˆ˜๋ก ๋งค์นญ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
  • TM_CCOEFF_NORMED: ์ •๊ทœํ™”๋œ ์ƒ๊ด€ ๊ณ„์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๊ฒฐ๊ณผ ๊ฐ’์€ 0๊ณผ 1 ์‚ฌ์ด๋กœ, 1์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ๋งค์นญ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • TM_CCORR: ์ƒ๊ด€์„ ์‚ฌ์šฉํ•˜์—ฌ ๋งค์นญํ•œ๋‹ค. ๊ฐ’์ด ํด์ˆ˜๋ก ๋งค์นญ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
  • TM_CCORR_NORMED: ์ •๊ทœํ™”๋œ ์ƒ๊ด€์„ ์‚ฌ์šฉํ•œ๋‹ค. ๊ฒฐ๊ณผ ๊ฐ’์€ 0๊ณผ 1 ์‚ฌ์ด๋‹ค.
  • TM_SQDIFF: ์ œ๊ณฑ ์ฐจ์ด๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๋งค์นญํ•œ๋‹ค. ๊ฐ’์ด ์ž‘์„์ˆ˜๋ก ๋งค์นญ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
  • TM_SQDIFF_NORMED: ์ •๊ทœํ™”๋œ ์ œ๊ณฑ ์ฐจ์ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๊ฒฐ๊ณผ ๊ฐ’์€ 0๊ณผ 1 ์‚ฌ์ด๋กœ, 0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ๋งค์นญ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

 

Cascade Classifier

์บ์Šค์ผ€์ด๋“œ ๋ถ„๋ฅ˜๊ธฐ(Cascade Classifier)๋Š” ์—ฌ๋Ÿฌ ๋‹จ๊ณ„์˜ ๋ถ„๋ฅ˜๊ธฐ๋ฅผ ์—ฐ์†์ ์œผ๋กœ ์ ์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ๊ฒ€์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

 

์ด ๋ฐฉ๋ฒ•์€ ์ฃผ๋กœ Haar ํŠน์„ฑ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, ์ด๋ฏธ์ง€์—์„œ ํŠน์ • ํŒจํ„ด์ด๋‚˜ ๊ฐ์ฒด๋ฅผ ๋น ๋ฅด๊ฒŒ ์ธ์‹ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ๋‹ค.

 

์บ์Šค์ผ€์ด๋“œ ๊ตฌ์กฐ๋กœ ๋˜์–ด์žˆ์–ด, ์ดˆ๊ธฐ ๋‹จ๊ณ„์— ๊ฐ„๋‹จํ•œ ํŠน์ง•์„ ๊ฒ€์‚ฌ, ์ดํ›„ ๋‹จ๊ณ„๋ฅผ ์ง„ํ–‰ํ• ์ˆ˜๋ก ๋” ๋ณต์žกํ•œ ํŠน์ง•์„ ๊ฒ€์‚ฌํ•˜๊ฒŒ ๋œ๋‹ค.

์ด๋Ÿฌํ•œ ๊ตฌ์กฐ๋กœ ๋ถˆํ•„์š”ํ•œ ๊ณ„์‚ฐ์„ ์ค„์ด๊ณ , ์†๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.

 

์บ์Šค์ผ€์ด๋“œ ๋ถ„๋ฅ˜๊ธฐ์˜ ๋ถ„๋ฅ˜ ๋‹จ๊ณ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.(ex. ์–ผ๊ตด)

  • ์˜์ƒ ์ž…๋ ฅ : 1๋‹จ๊ณ„๋กœ 
  • 1๋‹จ๊ณ„(ํŠน์ง• ํ•œ๊ฐœ ์‚ฌ์šฉ) : Pass ๊ฒฝ์šฐ ๋‹ค์Œ ๋‹จ๊ณ„, Fail ๊ฒฝ์šฐ ์–ผ๊ตด ์•„๋‹˜
  • 2๋‹จ๊ณ„(ํŠน์ง• ๋‹ค์„ฏ๊ฐœ ์‚ฌ์šฉ) : Pass ๊ฒฝ์šฐ ๋‹ค์Œ ๋‹จ๊ณ„, Fail ๊ฒฝ์šฐ ์–ผ๊ตด ์•„๋‹˜
  • 3๋‹จ๊ณ„(ํŠน์ง• 20๊ฐœ ์‚ฌ์šฉ) : Pass ๊ฒฝ์šฐ ๋‹ค์Œ ๋‹จ๊ณ„, Fail ๊ฒฝ์šฐ ์–ผ๊ตด ์•„๋‹˜
  • ....
  • ์ตœ์ข… ๋‹จ๊ณ„(ํŠน์ง• n๊ฐœ ์‚ฌ์šฉ) : Pass์˜ ๊ฒฝ์šฐ ์–ผ๊ตด, Fail ๊ฒฝ์šฐ ์–ผ๊ตด ์•„๋‹˜

 

์บ์Šค์ผ€์ด๋“œ ๋ถ„๋ฅ˜๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์—ฌ๊ธฐ์„œ ์‚ฌ์ „ํ•™์Šต ๋œ ๋ถ„๋ฅ˜๊ธฐ ํŒŒ์ผ์ด ํ•„์š”ํ•˜๋‹ค.

 

opencv/data/haarcascades at master · opencv/opencv

Open Source Computer Vision Library. Contribute to opencv/opencv development by creating an account on GitHub.

github.com

 

import cv2

image = cv2.imread("human.jpg")
image = cv2.resize(image,(int(image.shape[1]//2),int(image.shape[0]//2)),interpolation=cv2.INTER_LANCZOS4)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# ๋ถ„๋ฅ˜๊ธฐ ๋กœ๋“œ
eye_cascade = cv2.CascadeClassifier("haarcascade_eye.xml")

# ๋ˆˆ ๊ฒ€์ถœ
eyes = eye_cascade.detectMultiScale(gray,scaleFactor=1.1,minNeighbors=5,minSize=(60,60))

# ๋ฐ”์šด๋”ฉ ๋ฐ•์Šค
for (x, y, w, h) in eyes:
    cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2)

cv2.imshow("Cascade Classifier",image)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

HOG ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ†ตํ•œ ๋ณดํ–‰์ž ๊ฒ€์ถœ

HOG(Histogram of Oriented Gradients)๋Š” ์ด๋ฏธ์ง€ ๊ธฐ์šธ๊ธฐ ๋ฐฉํ–ฅ๊ณผ ํฌ๊ธฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ํŠน์ง• ์ถ”์ถœ ๋ฐฉ๋ฒ•์ด๋‹ค.

์ด ๋ฐฉ๋ฒ•์€ ๊ฐ์ฒด์˜ ๋ชจ์–‘์„ ํ‘œํ˜„ํ•˜๋Š”๋ฐ ๊ฐ•๋ ฅํ•œ ์„ฑ๋Šฅ์„ ๋ณด์ด๋ฉฐ, ํŠนํžˆ ๋ณดํ–‰์ž์™€ ๊ฐ™์€ ์‚ฌ๋žŒ์˜ ํ˜•ํƒœ๋ฅผ ์ธ์‹ํ•˜๋Š”๋ฐ ํšจ๊ณผ์ ์ด๋‹ค.

  • ์ด๋ฏธ์ง€์—์„œ ์ž‘์€ ์…€(cell)๋กœ ๋‚˜๋ˆ„๊ณ , ๊ฐ ์…€์˜ ๊ธฐ์šธ๊ธฐ ๋ฐฉํ–ฅ์„ ๊ณ„์‚ฐํ•œ๋‹ค.
  • ๊ฐ ์…€์—์„œ ๊ธฐ์šธ๊ธฐ ๋ฐฉํ–ฅ์˜ ํžˆ์Šคํ† ๊ทธ๋žจ์„ ์ƒ์„ฑ, ์ด๋ฅผ ๊ฒฐํ•ฉํ•ด ์ „์ฒด ์ด๋ฏธ์ง€์˜ ํŠน์ง• ๋ฒกํ„ฐ๋ฅผ ๋งŒ๋“ ๋‹ค.

 

import cv2

# HOG ๋ถ„๋ฅ˜๊ธฐ ์ดˆ๊ธฐํ™”
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())

# ์ด๋ฏธ์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
image = cv2.imread('people.jpg')

# ๋ณดํ–‰์ž ๊ฒ€์ถœ
boxes, weights = hog.detectMultiScale(image, winStride=(8, 8), padding=(8, 8), scale=1.05)

# ๊ฒ€์ถœ๋œ ๋ณดํ–‰์ž์— ์‚ฌ๊ฐํ˜• ๊ทธ๋ฆฌ๊ธฐ
for (x, y, w, h) in boxes:
    cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)

# ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ํ‘œ์‹œ
cv2.imshow('Detected Pedestrians', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

QR ์ฝ”๋“œ ๊ฒ€์ถœ

import cv2

# ์ด๋ฏธ์ง€ ํŒŒ์ผ ์ฝ๊ธฐ
image = cv2.imread('qr.png')
if image is None:
    pass
else:
    # QR ์ฝ”๋“œ ๊ฒ€์ถœ๊ธฐ ์ดˆ๊ธฐํ™”
    detector = cv2.QRCodeDetector()

    # QR ์ฝ”๋“œ ๊ฒ€์ถœ
    data, bbox, _ = detector.detectAndDecode(image)

    # ๊ฒ€์ถœ๋œ ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ
    if data:
        print("QR ์ฝ”๋“œ ๋‚ด์šฉ:", data)
        # QR ์ฝ”๋“œ์˜ ๊ฒฝ๊ณ„ ์ƒ์ž ๊ทธ๋ฆฌ๊ธฐ
        if bbox is not None:
            for i in range(len(bbox)):
                cv2.polylines(image, [bbox[i].astype(int)], isClosed=True, color=(0, 255, 0), thickness=2)

    # ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ํ‘œ์‹œ
    cv2.imshow('QR Code Detection', image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

 

728x90
๋ฐ˜์‘ํ˜•