python OpenCV 라이브러리를 사용해
특정 이미지 사진에서 사진안에 객체를 검출해 사각형으로 만들고 그 너비와 높이를 구하는 소스코드를 구현해보았다
openCV 공식 문서와 chatGPT를 이용해 구현한 예제 코드라고 보면 될 듯 하다
소스코드는 Anaconda Navigator 에서 Jupyter 노트북을 사용해 구현하였다
먼저 필요한 라이브러리 임포트
import cv2
import numpy as np
객체검출할 이미지 파일 불러오기
# 이미지 로드
image = cv2.imread('D:/_PCB_yolo/test/pcb4.jpg') #로컬 파일의 풀 경로
이미지 크기 변환이 필요한 경우 가로세로 해상도를 얻고 비율만큼 확대 축소 진행
# 이미지의 가로, 세로 해상도 얻기
height, width = image.shape[:2]
# 이미지 축소
image = cv2.resize(image, (width // 4, height // 4)) #4분의1크기로 축소
#image = cv2.resize(image, (width * 3, height * 3)) #3배로 확대
height_resize, width_resize = image.shape[:2]
print("height_resize",height_resize)
print("width_resize",width_resize)
안에 그림이 복잡하게 되어있어서 색상코드를 이용해 객체를 검출하도록 구현
색상 hex 코드를 이용해 HSV로 바꾸고 수동으로 색상,채도,밝기 조절
입력값으로 hex 코드를 받아서 HSV로 바꿔줘도된다
# 이미지를 HSV 컬러 스페이스로 변환
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 초록색 범위 지정 (색상, 채도, 밝기)
lower_green = np.array([30, 50, 50]) # 낮은 Hue 범위
upper_green = np.array([100, 255, 255]) # 높은 Hue 범위
# 이미지에서 초록색 범위 내의 영역을 마스크로 생성
mask = cv2.inRange(hsv, lower_green, upper_green)
이후 사용할 변수 지정
#스케일 변수 설정 추후에 px->mm 등으로 단위변환 시 사용
scale = 0.1
thickness = 2 # 테두리 두께
font_scale = 0.5 # 폰트 스케일
# 폰트
font = cv2.FONT_HERSHEY_SIMPLEX
# 텍스트 색상
white = (255, 255, 255)
red = (0, 0, 255)
black = (0, 0, 0)
green = (0, 255, 0)
사각형으로 객체 검출
# 마스크를 사용하여 초록색 사각형을 검출
# findContours 함수는 입력 이미지에서 윤곽선을 찾아 해당 윤곽선을 표현하는 좌표 정보를 반환
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#받은 좌표들 for문
for contour in contours:
# 검출된 초록색 사각형의 꼭짓점 좌표와 크기를 얻음
rect = cv2.minAreaRect(contour)
box = cv2.boxPoints(rect)
box = np.int0(box)
# 검출된 사각형의 면적 계산
area = cv2.contourArea(contour)
w = int(rect[1][0])
h = int(rect[1][1])
x = int(rect[0][0])
y = int(rect[0][1])
# 밀리미터 단위로 변환
w_mm = int(rect[1][0] * scale)
h_mm = int(rect[1][1] * scale)
x_mm = int(rect[0][0] * scale)
y_mm = int(rect[0][1] * scale)
#면적이 100이상인거로만 검출
if area>100:
print("사각형의 면적: {} 픽셀".format(area))
print("너비: {} 픽셀, 높이: {} 픽셀".format(w, h))
print("너비: {} mm, 높이: {} mm".format(w_mm, h_mm))
# 회전된 사각형 그리기
cv2.drawContours(image, [box], 0, green, thickness)
# 네가지 (x, y) 좌표 출력
cv2.putText(image, "Scale: {}, Width: {} px, Height: {} px ".format(scale, w, h), (10,20), font, font_scale, black, thickness)
cv2.putText(image, "Width: {} mm, Height: {} mm ".format(w_mm, h_mm), (10,40), font, font_scale, black, thickness)
#좌표 텍스트가 이미지 밖에 위치하는거 막는 소스
position_0_x = box[0][0]
position_0_y = box[0][1]
if position_0_x > width_resize - 100 :
position_0_x = width_resize - 100
if position_0_y > height_resize - 100 :
position_0_y = height_resize - 100
position_1_x = box[1][0]
position_1_y = box[1][1]
if position_1_x > width_resize - 100 :
position_1_x = width_resize - 100
if position_1_y > height_resize - 100 :
position_1_y = height_resize - 100
position_2_x = box[2][0]
position_2_y = box[2][1]
if position_2_x > width_resize - 100 :
position_2_x = width_resize - 100
if position_2_y > height_resize - 100 :
position_2_y = height_resize - 100
position_3_x = box[3][0]
position_3_y = box[3][1]
if position_3_x > width_resize - 100 :
position_3_x = width_resize - 100
if position_3_y > height_resize - 100 :
position_3_y = height_resize - 100
#이미지 위에 텍스트로 표현
cv2.putText(image, f'({box[0][0]}, {box[0][1]})', (position_0_x, position_0_y), font, font_scale, red, thickness)
cv2.putText(image, f'({box[1][0]}, {box[1][1]})', (position_1_x, position_1_y), font, font_scale, red, thickness)
cv2.putText(image, f'({box[2][0]}, {box[2][1]})', (position_2_x, position_2_y), font, font_scale, red, thickness)
cv2.putText(image, f'({box[3][0]}, {box[3][1]})', (position_3_x, position_3_y), font, font_scale, red, thickness)
결과 이미지 출력
# 결과 이미지 출력
cv2.imshow("Detected Green Rectangle", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
회전된 이미지도 잘 따고 결과도 깔끔하니 잘 나온 듯 하다.
색상 코드의 파라미터 조정해가며 최대한 테두리를 깔끔하게 검출하도록 하는 수동적인 수정이 필요해서 살짝 번거롭긴했다,,
다음엔 다각형모양으로 외곽선을 검출해서 좌표따는 소스를 구현할 예정!!
'업무일지 > 기술' 카테고리의 다른 글
[Ubuntu] MariaDB 외부 ip로 접속 안되는 삽질 해결 (0) | 2023.03.06 |
---|---|
[Node.js] Next.js(Node.js)에서 mysqldump 시도하기 (0) | 2023.02.02 |
[JS] React 에서 jsx단 에러처리하기 (1) | 2022.12.13 |
[Next.js] 외부접속시 데이터 fetch 에러.. (0) | 2022.07.29 |
[Java]Timer 제 시간에 실행 못하던 버그 (0) | 2022.04.25 |