250909 [ Day 46 ] - OpenCV (2)

TaeHyun·2025년 9월 9일

TIL

목록 보기
48/182

시작하며

어제에 이어서 OpenCV의 기본적인 사용 방법들에 대해서 공부했다. 이미지의 색을 변경하고 여러 도형을 그리는 등 NumPy를 사용해서 이미지의 데이터를 변경하는 과정을 계속 배우는 중이다.

이미지 기본 조작

일부 영역 색칠

  • OpenCV = B G R 순서
img = np.zeros((460, 640, 3), dtype=np.uint8)

# 일부 색 변경
img[200:300, 300:400] = (0,0,255)
# 전체 하얀색으로 변경
img[:] = (255,255,255)

cv.imshow("Color", img)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

  • 이미지에 색칠하기
DOG_PATH = "../images/dog.jpg"

img = cv.imread(DOG_PATH)

img[200:300, 300:400] = (0,0,255)

cv.imshow("Photo", img)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

  • 이미지 자르기
img = cv.imread(DOG_PATH)

crop = img[70:320, 300:450].copy()
img[0:250, 0:150] = crop

cv.imshow("img", img)
cv.imshow("Cropped", crop)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

얕은 복사 / 깊은 복사

  • 얕은 복사 : 메모리 연결(참조) 유지 (서로의 변경 사항을 공유)
  • 깊은 복사 : 메모리 연결(참조) 해제 (완전 복사)
img = np.zeros((460, 640, 3), dtype=np.uint8)

# 얕은 복사
shallow_copy = img[200:300, 300:400]
shallow_copy[:] = (255,0,255)

# 깊은 복사
deep_copy = img[200:300, 300:400].copy()
deep_copy[:] = (255,255,0)

cv.imshow("original", img)
cv.imshow("shalliw copy", shallow_copy)
cv.imshow("deep copy", deep_copy)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

색상 변경

  • cv2.cvtColor(img, code)
img = cv.imread(DOG_PATH)

gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB)

cv.imshow("img", img)
cv.imshow("gray", gray)
cv.imshow("rgb", rgb)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

  • 색상 반전 : 255 - color
img = cv.imread(DOG_PATH)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

inverted = 255 - gray

cv.imshow("gray", gray)
cv.imshow("inverted", inverted)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

이미지 채널 분리와 병합

  • cv2.split(img) : 이미지 채널 분리
  • cv2.merge(b,g,r) : 이미지 채널 병합
# 이미지 채널 분리
img = cv.imread(DOG_PATH)
b, g, r = cv.split(img)

cv.imshow("Blue", b)
cv.imshow("Green", g)
cv.imshow("Red", r)

# 이미지 채널 병합
merged = cv.merge([b,g,r])

cv.imshow("Merged", merged)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

이미지 리사이즈

  • cv2.resize(img, (size), fx, fy, interpolation)
  • (size) : 사이즈를 직접 입력할 경우
  • fx, fy : 비율로 사이즈를 조정할 경우
  • interpolation : 보간법 (이미지를 조정할 때 생기는 픽셀 사이의 빈 공간을 채우는 방법)
img = cv.imread(DOG_PATH)

dst = cv.resize(img, (1280, 800))
near = cv.resize(img, None, fx=3, fy=3, interpolation=cv.INTER_NEAREST)
cubic = cv.resize(img, None, fx=3, fy=3, interpolation=cv.INTER_CUBIC)

cv.imshow("original", img)
cv.imshow("resized", dst)
cv.imshow("near", near)
cv.imshow("cubic", cubic)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

  • 비디오 리사이즈
DOG_VIDEO_PATH = "../videos/dog.mp4"

cap = cv.VideoCapture(DOG_VIDEO_PATH)
fps = cap.get(cv.CAP_PROP_FPS)

while cap.isOpened():
    ret, frame = cap.read()

    if not ret:
        break

    dst = cv.resize(frame, None, fx=1.5, fy=1.5, interpolation=cv.INTER_CUBIC)

    cv.imshow("Original Video", frame)
    cv.imshow("Resized Video", dst)
    
    if cv.waitKey(int(1000/fps)) == ord("q"):
        break

cap.release()
cv.destroyAllWindows()
cv.waitKey(1)

이미지 피라미드

  • 고정된 비율로 이미지를 확대/축소
  • 확대/축소시 가우시안 블러 처리를 통해 이미지를 부드럽게 변환
  • cv2.pyrUp(img) : 이미지를 2배 키움
  • cv2.pyrDown(img) : 이미지를 1/2로 줄임
img = cv.imread(DOG_PATH)

size_up = cv.pyrUp(img)
size_down = cv.pyrDown(img)

cv.imshow("original", img)
cv.imshow("Up", size_up)
cv.imshow("Down", size_down)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

이미지 대칭

  • cv2.flip(img, code)
    • code : 대칭의 방향을 결정
      • code > 0 : y축 반전(좌우반전)
      • code == 0 : x축 반전(상하반전)
      • code < 0 : x,y축 반전(상하좌우반전)
img = cv.imread(DOG_PATH)

flip_y = cv.flip(img, 1)
flip_x = cv.flip(img, 0)
flip_xy = cv.flip(img, -1)

cv.imshow("Original", img)
cv.imshow("Flip y", flip_y)
cv.imshow("Flip x", flip_x)
cv.imshow("Flip xy", flip_xy)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

도형 그리기

선 그리기

  • cv2.line(img, start, end, color, thickness, lineType)
img = np.zeros((460, 640, 3), dtype=np.uint8)

COLOR = (0,255,255)
THICKNESS = 5

cv.line(img, (100,100), (300,300), COLOR, THICKNESS, cv.LINE_4)
cv.line(img, (150,100), (350,300), COLOR, THICKNESS, cv.LINE_8)
cv.line(img, (200,100), (400,300), COLOR, THICKNESS, cv.LINE_AA)

cv.imshow("Line", img)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

원 그리기

  • cv2.circle(img, center, radius, color, thickness, lineType)
  • cv2.FILLED : 도형의 속을 채우는 옵션, thickness 위치에 적용
img = np.zeros((460, 640, 3), dtype=np.uint8)

RADIUS = 50
COLOR = (255,0,0)
THICKNESS = 10

# 속이 비어있는 원
cv.circle(img, (200, 200), RADIUS, COLOR, THICKNESS, cv.LINE_AA)

# 속이 채워진 원
cv.circle(img, (400, 200), RADIUS, COLOR, cv.FILLED, cv.LINE_AA)

cv.imshow("Circle", img)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

타원 그리기

  • cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness, lineType)
img = np.zeros((460, 640, 3), dtype=np.uint8)

COLOR = (255,0,0)
THICKNESS = 10

cv.ellipse(img, (320, 230), (100, 50), 30, 0, 270, COLOR, THICKNESS, cv.LINE_AA)

cv.imshow("Ellipse", img)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

사각형 그리기

  • cv2.rectangle(img, start, end, color, thickness, lineType)
img = np.zeros((460, 640, 3), dtype=np.uint8)

COLOR = (255,0,0)
THICKNESS = 5

# 속이 비어있는 사각형
cv.rectangle(img, (150, 100), (250, 200), COLOR, THICKNESS, cv.LINE_AA)
# 속이 채워진 사각형
cv.rectangle(img, (300, 100), (400, 200), COLOR, cv.FILLED, cv.LINE_AA)

cv.imshow("Rectangle", img)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

다각형 그리기 (선)

  • cv2.polylines(img, pts, isClosed, color, thickness, lineType)
    • pts : 다각형 선분의 배열(Numpy 배열)
    • isClosed : 다각형을 닫을지를 결정
img = np.zeros((460, 640, 3), dtype=np.uint8)

pts = np.array([[[100,100], [200,100], [100,200]]])
COLOR = (255,255,255)
THICKNESS = 10

cv.polylines(img, pts, True, COLOR, THICKNESS)

cv.imshow("Poltlines", img)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

다각형 그리기 (채우기)

  • cv2.fillpoly(img, pts, color)
img = np.zeros((460, 640, 3), dtype=np.uint8)

pts = np.array([[ [200,200], [300,200], [200,300] ]])
COLOR = (255,255,255)

cv.fillPoly(img, pts, COLOR)

cv.imshow("FillPoly", img)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

텍스트 그리기(영어)

  • cv2.putText(img, text, position, font, scale, color, thickness)
  • OpenCV 에서는 한글 텍스트 그리기 지원 X -> 우회적 방법 사용
img = np.zeros((460, 640, 3), dtype=np.uint8)

SCALE = 1
THICKNESS = 2
COLOR = (255,255,255)

cv.putText(img, "Hello World!", (220,200), cv.FONT_HERSHEY_DUPLEX, SCALE, COLOR, THICKNESS)
cv.putText(img, "OpenCV Study", (200,260), cv.FONT_HERSHEY_COMPLEX | cv.FONT_ITALIC, SCALE, COLOR, THICKNESS)

cv.imshow("Text", img)

cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)

마치며

아직까지는 기능을 익히는 과정이라 어려운 건 없었는데, 내일부터 본격적으로 어려운 내용들을 배운다고 한다. OpenCV에 NumPy가 상당히 많이 사용되는 것 같아서 NumPy도 계속 복습하면서 잘 배워가야 할 것 같다.

NOTION

MY NOTION (OpenCV. 01)

profile
Hello I'm TaeHyunAn, Currently Studying Data Analysis

0개의 댓글