컴퓨터 비전 입문 2: 이미지 기초

이 튜토리얼은 시리즈의 “레슨 2″로 제공되는 컴퓨터 비전의 기초입니다. 추가로 진행되는 레슨들에서는 자신만의 딥러닝 기반 컴퓨터 비전 프로젝트를 구축하는 범위에 대해 이야기할 것입니다. 전체 강의 목차와 목록은 여기에서 확인하실 수 있습니다..

이 문서의 주요 요점:

  • 디스크에서 이미지 로드.
  • 이미지의 ‘높이’, ‘너비’, ‘깊이’ 확인.
  • 이미지의 R, G, B 구성 요소 찾기.
  • OpenCV를 사용한 그리기.

디스크에서 이미지 로드

이미지에 어떤 작업이나 조작을 수행하기 전에, 우리가 선택한 이미지를 디스크에 로드하는 것이 중요합니다. 이 작업은 OpenCV를 사용하여 수행할 것입니다. 이미지를 로드하는 두 가지 방법이 있습니다. 한 가지 방법은 이미지 경로와 이미지 파일을 OpenCV의 “imread” 함수에 간단히 전달하여 이미지를 로드하는 것입니다. 다른 방법은 명령줄 인수를 사용하여 이미지를 전달하고, 파이썬 모듈 argparse를 사용하는 것입니다.

Fig 2.1 Loading an Image from Disk by hard coding the image path and name in code.

Python

 

#디스크에서 이미지 로드

import cv2
image = cv2.imread(“C:/Sample_program/example.jpg”)
cv2.imshow(‘Image’, image)
cv2.waitKey(0)

먼저, 메모장++에서 Loading_image_from_disk.py라는 파일을 만들어 보겠습니다. 먼저, 이미지 처리 함수를 포함하는 OpenCV 라이브러리를 가져옵니다. 첫 번째 코드 줄에서 cv2를 사용하여 라이브러리를 가져옵니다. 두 번째 코드 줄에서는 OpenCV의 cv2.imread 함수를 사용하여 이미지를 읽고, 이미지의 경로를 매개변수로 전달합니다. 경로는 .jpg, .jpeg, .png 또는 .tiff 이미지 형식 확장자와 함께 파일 이름을 포함해야 합니다.

구문// image=cv2.imread(“path/to/your/image.jpg”) //

파일 확장명을 지정할 때 절대적으로 주의해야 합니다. 잘못된 확장명을 제공하면 다음과 같은 오류를 받게 됩니다.

Python

 

ERROR :

c:\Sample_program>python Loading_image_from_disk.py
Traceback (most recent call last):
File “Loading_image_from_disk.py”, line 4, in <module>
cv2.imshow(‘Image’, image)
cv2.error: OpenCV(4.3.0) C:\projects\opencv-python\opencv\modules\highgui\src\window.cpp:376: error: (-215:Assertion failed) size.width>0 && size.height>0 in function ‘cv::imshow’

세 번째 코드 줄에서는 실제로 로드된 이미지를 표시합니다. 첫 번째 매개변수는 문자열이거나 창의 “이름”입니다. 두 번째 매개변수는 이미지가 로드된 개체입니다.

마지막으로, cv2.waitKey 호출은 키보드에서 키를 누를 때까지 스크립트의 실행을 일시 중지합니다. “0” 매개변수를 사용하면 모든 키 입력이 실행을 다시 시작하게 합니다. 마지막 코드 줄을 프로그램에서 제외하고 프로그램을 실행하여 차이를 확인해 보십시오.

Fig 2.2 Loading an Image using Argparse module.

Python

 

#Argparse를 사용하여 디스크에서 이미지 읽기

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

image = cv2.imread(args[“image”])
cv2.imshow(‘Image’, image)
cv2.waitKey(0)

명령줄 인수(argparse)를 사용하여 이미지 또는 파일을 읽는 방법을 아는 것은 절대적으로 필요한 기술입니다.

처음 두 줄의 코드는 필요한 라이브러리를 가져오는 것입니다. 여기서 OpenCV와 Argparse를 가져옵니다. 이 과정에서 계속해서 반복됩니다.

다음 세 줄의 코드는 명령줄 인수를 파싱하는 데 처리합니다. 필요한 유일한 인수는 — image입니다: 디스크상의 이미지 경로입니다. 마지막으로 인수를 파싱하고 args라는 사전에 저장합니다.

잠시 시간을 내어 — image 스위치가 정확히 무엇인지 논의해 보겠습니다. — image “스위치”(“스위치”는 “명령줄 인수”의 동의어로 두 용어를 서로 대체하여 사용할 수 있음)는 명령줄에서 지정하는 문자열입니다. 이 스위치는 Loading_image_from_disk.py 스크립트에게 우리가 로드하고자 하는 이미지가 디스크상의 어디에 있는지 알려줍니다.

마지막 세 줄의 코드는 이전에 논의되었습니다; cv2.imread 함수는 args[“image”]를 매개변수로 사용하는데, 이는 명령 프롬프트에서 제공하는 이미지입니다. cv2.imshow는 이전 줄에서 이미 이미지 객체에 저장된 이미지를 표시합니다. 마지막 줄은 키보드에서 키를 누를 때까지 스크립트의 실행을 일시 중지합니다.

argparse — 명령줄 인수를 사용하는 주요 이점 중 하나는 프로그램에서 이미지 경로를 변경하지 않고도 다양한 폴더 위치에서 이미지를 로드할 수 있다는 것입니다. 동적으로 이미지 경로를 전달하여 파이썬 프로그램을 실행할 때 명령 프롬프트에서 인수로 이미지 경로를 제공합니다(예: “C:\CV_Material\image\sample.jpg”).

Fig 2.3 Loading Images from different folder locations using Argparse.

c:\Sample_program>python Loading_image_from_disk.py — image C:\CV_Material\session1.JPG

여기서는 Loading_image_from_disk.py 파이썬 파일을 c:\sample_program 위치에서 실행하고, 이미지 경로와 함께 “-image” 매개변수를 전달합니다C:\CV_Material\session1.JPG.

이미지의 ‘높이’, ‘너비’ 및 ‘깊이’ 획득

이미지가 NumPy 배열로 표현되기 때문에 .shape 속성을 간단히 사용하여 너비, 높이 및 채널 수를 조사할 수 있습니다.

방금 로드한 이미지 객체에 .shape 속성을 사용하여 이미지의 높이, 너비 및 깊이를 찾을 수 있습니다. 이전 강의 — 1에서 논의한 바와 같이 이미지의 높이와 너비는 MS 페인트에서 이미지를 열어 검증할 수 있습니다. 이전 강의를 참조하세요. 이미지의 깊이에 대해서는 다가오는 강의에서 논의하겠습니다. 깊이는 이미지의 채널이라고도 합니다. 컬러 이미지는 일반적으로 RGB 구성으로 픽셀에 대한 3채널이고 그레이 스케일 이미지는 1채널입니다. 이는 이전 Lesson-1에서 논의한 바였습니다.

Fig 2.4 Prints the Height, Width, and Depth of the Image.

Python

 

#이미지의 높이, 너비 및 깊이 얻기

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

#이전 코드와의 유일한 차이점 — 이미지 객체에 shape 속성 적용

print(f’(Height,Width,Depth) of the image is: {image.shape}’)

image = cv2.imread(args[“image”])
cv2.imshow(‘Image’, image)
cv2.waitKey(0)

출력:

이미지의 (높이, 너비, 깊이)는: (538, 723, 3)

이전 코드와의 유일한 차이점은 로드된 이미지 객체에 shape 속성을 적용하는 출력 문장입니다. f’ 는 변수를 동적으로 취하고 인쇄하는 F-문자열 또는 포맷팅된 문자열입니다.

f’ write anything here that you want to see in the print statement: {variables, variables, object, object.attribute,}’

여기서 우리는 이미지 객체의 높이, 너비 및 깊이를 계산하기 위해 꽃다발 괄호 안에 {object.attribute}를 사용하여 .shape 속성을 사용했습니다.

Python

 

#개별적으로 높이, 너비 및 깊이 얻기

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

image = cv2.imread(args[“image”])

# 높이, 너비 및 깊이를 개별적으로 얻기 위한 NumPy 배열 슬라이싱

print(“height: %d pixels” % (image.shape[0]))
print(“width: %d pixels” % (image.shape[1]))
print(“depth: %d” % (image.shape[2]))

cv2.imshow(‘Image’, image)
cv2.waitKey(0)

출력:

너비: 723픽셀
높이: 538픽셀
깊이: 3

여기서 튜플로 함께 (높이, 너비 및 깊이)를 얻는 대신 배열 슬라이싱을 수행하고 이미지의 높이, 너비 및 깊이를 개별적으로 얻습니다. 배열의 0번째 인덱스에는 이미지의 높이가 포함되어 있고, 1번째 인덱스에는 이미지의 너비가 포함되어 있으며, 2번째 인덱스에는 이미지의 깊이가 포함되어 있습니다.

이미지의 R, G 및 B 구성 요소 찾기

Fig 2.5 BGR value printed after taking the pixel co-ordinate position (y,x).

출력:

(321, 308) 위치의 이미지의 블루 그린 레드 구성 요소 값은: (238, 242, 253)

y 값이 x 값 앞에 전달되는 방식을 주목하십시오. 이 구문은 처음에는 직관적이지 않을 수 있지만 행렬에서 값에 액세스하는 방식과 일관됩니다. 먼저 행 번호를 지정한 다음 열 번호를 지정합니다. 거기에서 우리는 이미지의 블루, 그린 및 레드 구성 요소를 나타내는 튜플을 얻습니다.

또한 주어진 위치에서 픽셀의 색상을 변경하기 위해 작업을 반대로 할 수도 있습니다.

Python

 

# (x,y) 위치에서 이미지의 R,B,G 찾기

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

image = cv2.imread(args[“image”])

# RGB 값을 계산해야 하는 픽셀 좌표 값을 [y,x]로 사용자로부터 수신
[y,x] = list(int(x.strip()) for x in input().split(‘,’))

# 수신된 픽셀 좌표의 (블루, 그린, 레드) 값 추출
(b,g,r) = image[y,x]
print(f’The Blue Green Red component value of the image at position {(y,x)} is: {(b,g,r)}’)

cv2.imshow(‘Image’, image)
cv2.waitKey(0)

(b,g,r) = image[y,x] to image[y,x] = (b,g,r)

여기서 (BGR)의 색상을 이미지 픽셀 좌표에 할당합니다. 위치 (321,308)의 픽셀에 빨간색을 할당하고 해당 위치의 픽셀 BGR을 인쇄하여 동일한 것을 확인해 보겠습니다.

Python

 

#우리가 선택한 픽셀에 RGB 값을 할당하기 위해 작업을 반전

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

image = cv2.imread(args[“image”])

#사용자로부터 [y,x]로 픽셀 좌표 값을 수신하고, 해당 좌표의 RGB 값을 계산해야 합니다
[y,x] = list(int(x.strip()) for x in input().split(‘,’))

#수신된 픽셀 좌표의 (블루,그린,레드) 값 추출
image[y,x] = (0,0,255)
(b,g,r) = image[y,x]
print(f’The Blue Green Red component value of the image at position {(y,x)} is: {(b,g,r)}’)

cv2.imshow(‘Image’, image)
cv2.waitKey(0)

출력:

위치 (321, 308)에서 이미지의 블루, 그린 및 레드 구성 값은 (0, 0, 255)

위의 코드에서는 값을 입력하여 명령 프롬프트를 통해 픽셀 좌표를 수신하고 (블루, 그린, 레드)로 (0,0,255)를 할당하여 픽셀 좌표에 빨간색을 할당한 다음 입력 픽셀 좌표를 인쇄하여 동일한 것을 확인합니다.

OpenCV를 사용한 그리기

OpenCV를 사용하여 원을 그려 눈을 가리고, 사각형을 그려 입술과 내 옆에 있는 만타레이 물고기를 가리는 방법을 배워 보겠습니다.

출력은 다음과 같아야 합니다:

Fig 2.6 Masked Photo of me with the mantra-ray fish.

이 사진은 MS 페인트를 사용하여 모양으로 마스크되었습니다. 눈 주변에 원을 그리고 입술과 내 옆에 있는 만타레이 물고기를 가리기 위해 사각형을 그리면서 OpenCV를 사용하여 동일한 작업을 수행해 보겠습니다.

사각형을 그리려면 cv2.rectangle 메서드를 사용하고 OpenCV에서 원을 그리려면 cv2.circle 메서드를 사용합니다.

cv2.rectangle(이미지, (x1, y1), (x2, y2), (파랑, 초록, 빨강), 두께)

cv2.rectangle 메서드는 사각형을 그리고자 하는 이미지를 첫 번째 인수로 받습니다. 우리는 로드된 이미지 객체에 사각형을 그리고 싶으므로 이 객체를 메서드에 전달합니다. 두 번째 인수는 사각형의 시작 (x1, y1) 위치입니다. 여기서는 (156과 340) 위치에서 사각형을 시작합니다. 그 다음, 사각형의 끝 (x2, y2) 위치를 제공해야 합니다. 우리는 사각형을 (360, 450)에서 끝내기로 결정했습니다. 다음 인수는 그리고자 하는 사각형의 색상입니다. 이 경우, BGR 형식으로 검은색, 즉 (0,0,0)을 전달합니다. 마지막으로 전달하는 인수는 선의 두께입니다. 우리는 단단한 모양을 그리기 위해 -1을 주었으며, 이는 그림 2.6에서 볼 수 있습니다.

마찬가지로, cv2.circle 메서드를 사용하여 원을 그립니다.

cv2.circle(이미지, (x, y), r, (파랑, 초록, 빨강), 두께)

cv2.circle 메서드는 원을 그리고자 하는 이미지를 첫 번째 인수로 받습니다. 우리는 로드된 이미지 객체에 원을 그리고 싶으므로 이 객체를 메서드에 전달합니다. 두 번째 인수는 원의 중심 (343, 243) 위치입니다. 다음 인수는 원을 그리고자 하는 반지름입니다. 다음 인수는 원의 색상입니다. 이 경우, BGR 형식으로 빨간색, 즉 (0,0,255)를 전달합니다. 마지막으로 전달하는 인수는 선의 두께입니다. 우리는 단단한 모양을 그리기 위해 -1을 주었으며, 이는 그림 2.6에서 볼 수 있습니다.

좋아요! 이 모든 것을 알게 되었으니, 시작한 일을 완수해 보겠습니다. 이미지에서 도형을 그리기 위해서는 마스킹 영역의 시작 및 종료 (x,y) 좌표를 식별하여 해당 메서드에 전달해야 합니다.

어떻게 할까요?

다시 한 번 MS 페인트의 도움을 받아 보겠습니다. 마스킹할 영역의 좌표 중 하나(왼쪽 상단 또는 오른쪽 하단)에 커서를 놓으면, 좌표가 MS 페인트의 강조 표시된 부분에 표시되는 것을 볼 수 있습니다(그림 2.7 참조).

Fig 2.7 MSPaint to find the co-ordinates of the masking region.

마찬가지로 그림 2.8에 표시된 대로 모든 마스킹 영역에 대한 좌표 (x1,y1) (x2,y2)를 취합니다.

Fig 2.8 (x.y) Co-ordinates of masking regions.

Python

 

#OpenCV를 사용하여 눈, 입 및 가까운 물체 마스킹 그리기

import cv2
import argparse

apr = argparse.ArgumentParser()
apr.add_argument(“-i”, “ — image”, required=True, help=”Path to the image”)
args = vars(apr.parse_args())

image = cv2.imread(args[“image”])

cv2.rectangle(image, (415, 168), (471, 191), (0, 0, 255), -1)
cv2.circle(image, (425, 150), 15, (0, 0, 255), -1)
cv2.circle(image, (457, 154), 15, (0, 0, 255), -1)
cv2.rectangle(image, (156, 340), (360, 450), (0, 0, 0), -1)

#출력 이미지 표시
cv2.imshow(“Output drawing “, image)
cv2.waitKey(0)

결과:



Fig 2.9 Desired Output.

Source:
https://dzone.com/articles/computer-vision-tutorial-2-image-basics