목차
Mat 객체(C++)
넘파이 배열(PYTHON)
Mat 객체
OpenCV에서 이미지는 사용하는 언어에 따라 다른 객체에 저장됨.
- C++: 에는 Mat 클래스 타입의 객체에 저장
- Python: 경우에는 넘파이 배열에 저장
같은 이미지 데이터 공유
Mat 객체에 생성 생성자
나 대입 연산자
를 사용하면 이미지 데이터를 공유하는 객체를 생성.
1) 이미지에 생성 생성자와 대입 연산자를 각각 적용하여 새로운 Mat 객체를 생성한 후, 2) 하나의 Mat 객체에 이진화를 적용하면
3) 그림 처럼 나머지 2 개의 Mat 객체도 이진화 됨.
이미지 데이터를 공유하기 때문
# include < opencv2/opencv.hpp>
using namespace cv;
int main()
{
//1)
Mat img_color;
// 이미지를 읽어서 그레이 스케일 이미지로 변환합니다.
img_color = imread("cat on laptop.jpg", IMREAD_GRAYSCALE);
//2)
// 복사 생성자 // img_color 객체의 데이터를 공유하는 img_copyed1 객체를 생성합니다.
Mat img_copyed1(img_color);
// 대입 연산자 // img_color 객체의 데이터를 공유하는 img_copyed2 객체를 생성합니다.
Mat img_copyed2 = img_color;
//3)
// 하나의 Mat 객체에 이진화를 적용해봅니다.
threshold( img_color, img_color, 127, 255, THRESH_BINARY);
imshow("img_color", img_color);
imshow("img_copyed1", img_copyed1);
imshow("img_copyed2", img_copyed2);
waitKey(0);
}
ROI Region of Interest
Mat 객체의 이미지 데이터 중 일부분만 지정하여, 다른 Mat 객체를 가리키기 가능
이미지의 일부를 지정하는 것을 ROI (Region of Interest) 라고 함.
Rect 사용
Rect를 사용하여 사각형 영역을 지정
src( Rect( x, y, width, height)) )
- src : 관심영역을 설정할 원본 이미지
- Rect( x, y, width, height) )
- 관심영역을 설정할 사각형 정보, 좌표( x, y)를 시작으로 width 와 height 를 설정
[좌표 알아내는 법] 1) 그림판에서 이미지를 불러온다.
2) ROI로 지정할 사각형을 그려본다.
3) 각 사각형의 꼭짓점에 마우스를 올리면 하단에 픽셀 정보가 나온다 [000, 000 px]
4) 이렇 좌상단과 우하단 꼭짓점 좌표를 확인하면 width 와 height를 계산하기 쉽다
Range 사용
Range를 사용하여 특정 열과 행을 범위로 지정 가능.
Range(start_y, end_y), Range(start_x, end_x)
[사용하는 이유] 정확성을 높이기 위해 관찰하는 대상에 초점을 맞추는 것
한국어로 ‘관심영역 설정’
[주의] 이 경우에도 같은 이미지 데이터를 공유하기 때문에 하나의 Mat 객체를 이진화시키면 다른 Mat 객체에 영향을 줌 그러므로 원본이미지를 안건들이도록 주의해야 함.
# include < opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img_color;
img_color = imread("cat on laptop.jpg", IMREAD_GRAYSCALE);
// Rect(start_x, start_y, width, height)로 ROI할 영역을 // 지정합니다.
Mat img_sub1(img_color, Rect(20, 20, 150, 150));
// Range(start_y, end_y), Range(start_x, end_x)로 // ROI할 영역을 지정합니다.
// 본 예제에서는 전체 × 영역을 지정하기 위해
// Range::all()를 사용합니다.
Mat img_sub2 = img_color(Range(100, 150), Range::all());
// 하나의 Mat 객체에 이진화를 적용해봅니다.
threshold( img_sub1, img_sub1, 127, 255, THRESH_BINARY);
imshow("img_color", img_color);
imshow("img_sub1", img_sub1);
imshow("img_sub2", img_sub2);
waitKey(0);
}
이미지 복사본 생성
clone
과 CopyTo
: 새로운 메모리 공간에 이미지 데이터를 복사.
하나의 이미지를 이진화한다고 해서 다른 이미지에 영향을 주지 않음.
-> 원본이미지 손상 안됨
clone
복제 작업을 수행해주는 Clone 이라는 가상함수 생성하여 복제 Mat 복사된 이미지 이름 = 복사할 이미지 이름.clone()
copyTo
src.copyTo( dst )
src 이미지를 dst 에 복사
- src : 복사 시킬 원본 이미지
- dst : 복사 되어 저장 될 이미지 변수 메모리 값은 같지만 메모리주소가 달라 독립적인 이미지가 됨
OpenCV 에서는 ‘ = ‘ 표현을 아예 안 하는것이 낫다.
# include < opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img_color;
img_color = imread("cat on laptop.jpg", IMREAD_GRAYSCALE);
// clone 메소드를 사용하여 Mat 객체 img_color의 복사본을 만듭니다.
Mat img_copyed1 = img_color.clone();
// copyTo 메소드를 사용하여 Mat 객체 img_color의 복사본을 만듭니다.
Mat img_copyed2;
img_color.copyTo(img_copyed2);
// 하나의 Mat 객체에 이진화를 적용해봅니다.
threshold( img_color, img_color, 127, 255, THRESH_BINARY);
imshow("img_color", img_color);
imshow("img_copyed1", img_copyed1);
imshow("img_copyed2", img_copyed2);
waitKey(0);
}
넘파이 배열
more learn Numpy 파이썬에서 대입 연산자를 사용하면 2개의 변수가 같은 넘파이 배열을 가리킴.
수정을 하는 경우에는 서로 영향을 줌
[하지만] 하나의 이미지에 이진화 같은 OpenCV함수를 적용하면 다른 넘파이 배열에 영향 못줌.
- C++
- 1) 입력으로 사용한 Mat 객체를 OpenCV함수에서 처리 후,
- 2) 리턴되는 Mat 객체가 같음 파이썬에서는 OpenCV함수 적용 전후의 넘파이 배열이 달라짐
import cv2 as cv
img_gray = cv.imread("cat on laptop.jpg", cv.IMREAD_GRAYSCALE)
# 대입 연산자
img_copyed1 = img_gray
# img_gray 와 img_copyed1은 같은 넘파이 배열을 가리키게 됩니다.
# 같은 객체이므로 id함수의 리턴값이 같습니다.
print(id(img_gray), id(img_copyed1))
# 아직은 똑같은 넘파이 배열을 가리키기 때문에 # img_gray에 선을 그리면 img_copyed1에서 선이 그려집니다.
cv.line( img_gray, (0, 0), (100, 100), 0, 10 )
# img_gray에 이진화를 적용하여 결과를 img_gray에 저장하면 # img_gray와 img_copyed1는 별개의 넘파이 배열을 가리키게 됩니다.
ret,img_gray = cv.threshold( img_gray, 127, 255, cv.THRESH_BINARY)
# 다른 객체가 되므로 id함수의 리턴값이 달라집니다.
print(id(img_gray), id(img_copyed1))
# img_copyed1에는 영향을 주지 못하고 img_gray만 이진화됩니다.
cv.imshow("img_gray", img_gray) cv.imshow("img_copyed1", img_copyed1)
cv.waitKey(0)
ROI Region of Interest
이미지의 일부분을 지정하여 다른 변수에서 가리키게 하기
원본 이미지의 일부분을 ROI 넘파이 배열이 공유하게 됨.
- ROI에 직선을 그리면 원본 이미지에도 선이 그려짐
[하지만]
이진화 같은 OpenCV함수를 적용하면 서로 영향을 주지 않음.
앞의 경우와 마찬가지로 OpenCV함수에서 처리 후 리턴 되는 객체가 입력 객체와 다르기 때문.
새 변수 = 원래이미지[ start_y:end_y, start_x, end_x]
import cv2 as cv
img_gray = cv.imread("cat on laptop.jpg", cv.IMREAD_GRAYSCALE)
# [ start_y:end_y, start_x, end_y]로 ROI 영역을 지정합니다.
img_sub1 = img_gray[20:20+150, 20:20+150]
# img_sub1이 img_color의 일부 데이터를 공유하기 때문에 True가 리턴됩니다.
print(img_sub1.base is img_gray)
# 같은 이미지 데이터를 공유하기 때문에 img_sub1에 선을 그리면 # img_gray에도 선이 그려집니다.
cv.line( img_sub1, (0, 0), (100, 100), 0, 10 )
ret,img_sub1 = cv.threshold( img_sub1, 127, 255, cv.THRESH_BINARY)
# img_sub1가 입력과는 다른 객체가 되므로 False가 리턴됩니다.
print(img_sub1.base is img_gray)
# img_color에는 영향을 주지 못하고 img_sub1만 이진화됩니다.
cv.imshow("img_gray", img_gray)
cv.imshow("img_sub1", img_sub1)
cv.waitKey(0)
이미지 복사본 생성
파이썬에서는 이미지를 저장하기 위해 넘파이 배열을 사용
이미지 데이터 복사 시 넘파이의 copy 메소드
를 사용.
새로운 메모리 공간
에 이미지 데이터를 복사
-> 한쪽 이미지에 선을 그려도 다른 이미지에 영향을 주지 않음
import cv2 as cv
img_gray = cv.imread("cat on laptop.jpg", cv.IMREAD_GRAYSCALE)
# copy 메소드를 사용하여 img_color의 이미지 데이터를 복사합니다.
img_copyed1 = img_gray.copy()
# copy 메소드를 사용했기 때문에 img_color와 img_copyed1에 대한 # id 리턴값이 다릅니다. 별개의 객체라는 의미입니다.
print(id(img_gray), id(img_copyed1))
cv.line( img_gray, (0, 0), (100, 100), 0, 10 )
ret,img_gray = cv.threshold( img_gray, 127, 255, cv.THRESH_BINARY)
print(id(img_gray), id(img_copyed1))
cv.imshow("img_gray", img_gray)
cv.imshow("img_copyed1", img_copyed1)
cv.waitKey(0)