상세 컨텐츠

본문 제목

YOLOv3 알고리즘, haar cascade 방식으로 번호판 식별하기

자율주행/컴퓨터 비젼 프로젝트(python)

by nosungmin 2023. 2. 11. 16:51

본문

import cv2
import numpy as np
from google.colab.patches import cv2_imshow
weight_file = '/gdrive/My Drive/darknet/weights/yolov3.weights'
cfg_file = '/gdrive/My Drive/darknet/cfg/yolov3.cfg'
name_file = '/gdrive/My Drive/darknet/data/coco.names'
 
 

이 코드는 객체 검출(예: 사람, 자동차, 동물 등)을 수행하기 위해 YOLOv3 알고리즘을 사용하고, 이를 위해 필요한 파일들의 경로를 지정하는 부분입니다.

  • weight_file: 미리 학습된 가중치(weight)가 저장된 파일의 경로를 나타냅니다. 이 파일은 COCO 데이터셋에서 학습된 가중치를 저장하고 있습니다.
  • cfg_file: YOLOv3 네트워크의 구조 정보를 저장한 파일의 경로입니다. 이 파일은 미리 정의된 레이어(layer)와 그 파라미터(parameter) 정보 등이 저장되어 있습니다.
  • name_file: 객체 검출을 수행할 때, 각 클래스(class)에 대한 이름을 저장하고 있는 파일의 경로입니다. 이 파일은 COCO 데이터셋에서 사용된 클래스명을 저장하고 있으며, 각 클래스는 숫자로 구분됩니다.

 

min_confidence = 0.5 
 
# Load Yolo
net = cv2.dnn.readNet(weight_file, cfg_file)
 
classes = []
with open(name_file, 'r'as f:
    classes = [line.strip() for line in f.readlines()]

layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1for i in net.getUnconnectedOutLayers()]

print(classes)
 

이 코드는 YOLO(You Only Look Once) object detection 모델을 적용하기 위한 준비 단계입니다.

  1. classes 변수에 classes 정보를 읽어들입니다. name_file이라는 파일이 열리고, 파일의 각 줄에서 공백을 제거한 것들을 classes 리스트에 저장합니다.
  2. 모델에서 사용하는 layer_names를 가져오고, output_layers를 구성합니다. layer_names는 모델의 각 레이어의 이름을 가지고 있습니다. getUnconnectedOutLayers()는 output layer의 목록을 반환합니다. output_layers 리스트는 getUnconnectedOutLayers()에서 반환된 layer의 이름을 포함하고 있습니다.
  3. print(classes)는 classes의 내용을 화면에 출력하는 구문입니다. 코드가 올바르게 작동하는지 확인하기 위해서 사용할 수 있습니다.
img = cv2.imread('car2.jpg')
height, width, channels = img.shape

 

# Detecting objects
blob = cv2.dnn.blobFromImage(img, 0.00392, (416416), (000), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)

 

class_ids = []
confidences = []
boxes = []

 

for out in outs:
    for detection in out:
        scores = detection[5:]
        class_id = np.argmax(scores)
        confidence = scores[class_id]
        if confidence > min_confidence:
            # Object detected
            center_x = int(detection[0] * width)
            center_y = int(detection[1] * height)
            w = int(detection[2] * width)
            h = int(detection[3] * height)

 

            # Rectangle coordinates
            x = int(center_x - w / 2)
            y = int(center_y - h / 2)

 

            boxes.append([x, y, w, h])
            confidences.append(float(confidence))
            class_ids.append(class_id)

 

indexes = cv2.dnn.NMSBoxes(boxes, confidences, min_confidence, 0.4#인식률 0.4이상으로 중복되는 것만 인식하기
for i in range(len(boxes)):
    if i in indexes:
        if class_ids[i] == 2:#car만 고르게 만드는 조건문
            x, y, w, h = boxes[i]
            label = str(classes[class_ids[i]])
            print(i, class_ids[i], label)
            cv2.rectangle(img, (x, y), (x + w, y + h), (02550), 2)
            cv2.putText(img, label, (x, y + 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (02550), 1)  

 

cv2_imshow(img)     

저번에 만들었던 자동차 인식하기 코드

 

plate_cascade_name = 'haarcascade_russian_plate_number.xml'

이 코드는 OpenCV에서 제공하는 차량 번호판 검출을 위한 Haar Cascade 분류기 파일의 이름을 지정하는 부분입니다.

Haar Cascade는 이미지에서 객체를 검출하기 위한 머신러닝 기반 분류기 중 하나로, 이미지 내 특정 객체(예: 얼굴, 눈, 차량 등)의 특징을 추출하여 이를 기반으로 객체를 검출합니다. 차량 번호판 검출을 위해 사용되는 Haar Cascade 분류기 파일은 미리 학습된 분류기를 불러와 사용합니다. 이 코드에서는 haarcascade_russian_plate_number.xml 파일을 사용하여 차량 번호판을 검출할 수 있도록 합니다.

 

plate_cascade = cv2.CascadeClassifier()
#-- 1. Load the cascades
if not plate_cascade.load(cv2.samples.findFile(plate_cascade_name)):
    print('--(!)Error loading face cascade')
    exit(0)   

이 코드는 OpenCV의 Haar Cascade Classifier를 사용하여, 자동차 번호판(plate)을 인식하기 위한 cascade 분류기를 불러오는 과정입니다.

  • cv2.CascadeClassifier() 함수는 cascade 분류기 객체를 생성합니다.
  • cv2.samples.findFile(plate_cascade_name) 함수는 OpenCV에서 제공하는 샘플 데이터 중에서, plate_cascade_name에 해당하는 자동차 번호판 cascade 파일의 경로를 찾아줍니다.
  • plate_cascade.load() 함수는 찾아낸 cascade 파일을 plate_cascade 객체에 로드합니다.
  • if not plate_cascade.load(): 구문은 cascade 파일을 로드하는 과정에서 에러가 발생한 경우, --(!)Error loading face cascade라는 메시지를 출력하고 프로그램을 종료합니다.
  • exit(0) 함수는 프로그램을 종료합니다.
img = cv2.imread('russiacar.jpg')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.equalizeHist(gray)

height, width, channels = img.shape

# Detecting objects
blob = cv2.dnn.blobFromImage(img, 0.00392, (416416), (000), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)

이 코드는 YOLO(You Only Look Once) 객체 검출 알고리즘을 사용하여 이미지에서 객체를 검출하는 과정을 수행합니다.

cv2.dnn.blobFromImage() 함수는 입력 이미지를 네트워크에서 처리하기 적합한 형식으로 변환해주는 함수입니다. 변환된 이미지 데이터는 blob 변수에 저장됩니다. 이 함수의 인자로는 다음과 같은 값이 사용됩니다.

  • img: 변환할 이미지
  • 0.00392: 이미지 데이터에 곱해줄 배율 값
  • (416, 416): 변환된 이미지의 크기
  • (0, 0, 0): 이미지 데이터에 더해줄 평균 값
  • True: 이미지 채널을 BGR에서 RGB로 변경할 것인지 여부
  • crop=False: 이미지를 자를 것인지 여부

net.setInput(blob) 함수는 변환된 이미지 데이터를 YOLO 네트워크의 입력값으로 설정하는 역할을 합니다.

net.forward(output_layers) 함수는 YOLO 네트워크를 통과시킨 후, 출력 레이어에서 출력된 결과값들을 반환합니다. 이 결과값은 outs 변수에 저장됩니다. YOLO 알고리즘에서는 입력 이미지를 한 번에 처리하여 결과값을 출력하므로, 이 함수를 통해 반환된 outs는 전체 이미지에 대한 객체 검출 결과값입니다.


class_ids = []
confidences = []
boxes = []

for out in outs:
    for detection in out:
        scores = detection[5:]
        class_id = np.argmax(scores)
        confidence = scores[class_id]
        if confidence > min_confidence:
            # Object detected
            center_x = int(detection[0] * width)
            center_y = int(detection[1] * height)
            w = int(detection[2] * width)
            h = int(detection[3] * height)

            # Rectangle coordinates
            x = int(center_x - w / 2)
            y = int(center_y - h / 2)

            boxes.append([x, y, w, h])
            confidences.append(float(confidence))
            class_ids.append(class_id)

indexes = cv2.dnn.NMSBoxes(boxes, confidences, min_confidence, 0.4)
for i in range(len(boxes)):
    if i in indexes:
        if class_ids[i] == 2:#car만 고르게 만드는 조건문
            x, y, w, h = boxes[i]
            label = str(classes[class_ids[i]])
            print(i, class_ids[i], label)
     
            carROI = gray[y:y+h, x:x+w]
            cv2_imshow(carROI)
            plates = plate_cascade.detectMultiScale(carROI)
            print(plates)
            for (x2, y2, w2, h2) in plates:
                cv2.rectangle(img, (x+x2, y+y2), (x+x2 + w2, y+y2 + h2), (0255255), 2)

cv2_imshow(img)  
 

 

관련글 더보기