• Home
  • About
    • Yerim Oh photo

      Yerim Oh

      Happy and worthwhile day by day :)

    • Learn More
    • Email
    • LinkedIn
    • Instagram
    • Github
    • Youtube
  • Posts
    • All Posts
    • All Tags
  • Projects

[03] OpenCV 영상처리 ROI/복사본

07 Feb 2020

Reading time ~5 minutes

Table of Contents
  • 목차
  • Mat 객체(C++)
  • 넘파이 배열(PYTHON)
  • Mat 객체
    • 같은 이미지 데이터 공유
    • ROI Region of Interest
      • Rect 사용
      • Range 사용
    • 이미지 복사본 생성
      • clone
      • copyTo
  • 넘파이 배열
  • ROI Region of Interest
  • 이미지 복사본 생성

목차

Mat 객체(C++)

  • 같은 이미지 데이터 공유
  • ROI Region of Interest
    • Rect 사용
    • Range 사용
  • 이미지 복사본 생성
    • clone
    • copyTo

넘파이 배열(PYTHON)

  • 넘파이 배열
  • ROI Region of Interest
  • 이미지 복사본 생성

Mat 객체

OpenCV에서 이미지는 사용하는 언어에 따라 다른 객체에 저장됨.

  • C++: 에는 Mat 클래스 타입의 객체에 저장
  • Python: 경우에는 넘파이 배열에 저장

같은 이미지 데이터 공유

Mat 객체에 생성 생성자나 대입 연산자를 사용하면 이미지 데이터를 공유하는 객체를 생성.
1) 이미지에 생성 생성자와 대입 연산자를 각각 적용하여 새로운 Mat 객체를 생성한 후, 2) 하나의 Mat 객체에 이진화를 적용하면
3) 그림 처럼 나머지 2 개의 Mat 객체도 이진화 됨.
이미지 데이터를 공유하기 때문 image

# 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) image

[사용하는 이유] 정확성을 높이기 위해 관찰하는 대상에 초점을 맞추는 것
한국어로 ‘관심영역 설정’

[주의] 이 경우에도 같은 이미지 데이터를 공유하기 때문에 하나의 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]

image

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)

more learn is


이미지 복사본 생성

파이썬에서는 이미지를 저장하기 위해 넘파이 배열을 사용
이미지 데이터 복사 시 넘파이의 copy 메소드를 사용.
새로운 메모리 공간에 이미지 데이터를 복사 -> 한쪽 이미지에 선을 그려도 다른 이미지에 영향을 주지 않음

more learn 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)


OpenCV Share Tweet +1