Computer Vision

[The Core Functionality] Operations with Images

kka_nna 2020. 7. 25. 20:58

https://docs.opencv.org/master/d5/d98/tutorial_mat_operations.html

 

OpenCV: Operations with images

Prev Tutorial: Mask operations on matrices Next Tutorial: Adding (blending) two images using OpenCV Input/Output Images Load an image from a file: C++ Mat img = imread(filename); Java Mat img = Imgcodecs.imread(filename); Python If you read a jpg file, a 3

docs.opencv.org

Input & Output 

 

Image 로드하기 

Mat img = imread(filename);

jpeg filed을 로드하면 기본적으로 3 channel image type으로 생성된다. 

Grayscale image 를 원한다면, 

Mat img = imread(filename, IMREAD_GRAYSCALE);

 

Image 저장하기

imwrite(path+filename, img);

 

Basic Operations with Images

Accesing Pixel Intensity values

Scalr intensity = img.at<uchar>(y, x);
Scalar intensity = img.at<uchar>(Point(x,y)); // C++ version only

BGR color ordering 된 3 channel image 일 때, 

Vec3b intensity = img.at<Vec3b>(y,x);
uchar blue = intensity.val[0]; //uchar -> float
uchar green = intensity.val[1]; //ucahr -> float
uchar red = intensity.val[2]; //uchar -> float

Pixel의 intensity를 바꿀때도 같은 방법이 쓰인다. 

img.at<uchar>(y,x) = 128;

 

OpenCV에는 cv::projectPoints와 같은 calib3d 모듈의 Mat형식의 2D 또는 3D 포인트 배열을 갖는 함수가 있다. 행렬은 정확히 하나의 열을 포함해야 하며 각 행은 점에 해당하며 행렬 유형은 32FC2 또는 32FC3이어야 한다. 

vector<Point2f> points;
// . . . fill the array
Mat pointsMat = Mat(points);

그리고 Mat::at method를 통해서 matirx 안 point에 접근할 수 있다. 

Point2f point = pointsMat.at<Point2f>(i,0);

 

Memory management and Reference counting

Mat은 행렬/이미지 특성과 데이터에 대한 포인터를 유지하는 구조이다. 

따라서 동일한 데이터에 해당하는 Mat인스턴스가 여러개 있는 것을 막을수는 없다. 

Mat은 특정 Mat 인스턴스가 파괴 될 때마다 할당 해제해야하는 지 알려주는 참조 횟수를 유지한다. 

std::vector<Point3f> points;
// . . . fill the array
Mat poinsMat = Mat(points).reshape(1);

결과로, 1개의 열이 있는 32FC3행렬 대신 3개의 열이 있는 32FC1행렬을 얻는다. 

pointsMat : points의 데이터를 사용하며, 파괴시 메무리할당을 해제 하지 않는다. 

그러나 특정한 경우 개발자는points의 수명이 pointsMat보다 길게 설정해야한다. 

 

데이터를 복사해야하는 경우, cv::Mat::copyTo 또는 cv::Mat::clone을 사용해야한다. 

Mat img = imread("image.jpg");
Mat img1 = img.clone();

 

비어있는 Mat는 각 기능에 공급될 수 있따. 

각 구현은 대상 행렬에 대해 Mat:create를 호출한다. 

이 메소드는 비어있는 경우 행렬에 대한 데이터를 할당한다. 

비어있지 않고, 크기와 유형이 올바른 경우 이 방법은 아무 작업도 수행하지 않는다. 

그러나 크기 또는 유형이 입력 인수와 다른 ㄱ여우 데이터가 할당해제 되고 새 데이터가 할당된다. 

Mat img = imread( "image.jpg"); 
Mat sobels;
Soble(img, sobles, CV_32F, 1, 0);

 

Primitive Operations

행렬에는 여러가지 편리한 연산자가 있다. 

 

기존 그레이 스케일 이미지에서 검은색 이미지 만들기

img =Scalar(0);

 

관심 지역 선택

Rect r (10,10,100,100);
Mat smallImg = img(r);

 

Conversion from color to Gray Scale

Mat img = imread("image.jpg");
Mat grey;
cvtColor(img, grey, COLOR_BGR2GRAY);

 

Change image type from 8UC1 to 32FC1;

src.converTO9dst, CV_32F);

 

Visualizing Images

개발 과정에서 알고리즘의 중간 결과를 보는 것은 유용하다. 

Open CV는 편리한 이미지 시각화 방법을 제공한다. 

 

다음을 사용하여 8U이미지를 표시할 수 있다. 

Mat img = imread("image.jpg");
nameWindow ("image", WINDOW_AUTOSIZE));
imshow("image, img);
waitKey();

waitKey() 를 호출하면 "image"창에서 키 입력을 기다리는 메시지 전달주기가 시작된다. 

 

32F 이미지의 표시를 위해서는 8U유형으로 변환해야 한다. 

Mat img = imread("image.jpg");
Mat grey;
cvtColor(img, grey, COLOR_BGR2GRAY);
Mat sobelx;
Sobel(gre, sobelx, CV_32F, 1, 0);
double minval, maxVal;
minMaxLoc(sobelx, &minVal, &maxVal);
Mat draw;
sobelx.converTo(draw, CV_8U, 255.0/(maxVal - minVal), -minVal*255.0/(maxVal - minVal));
namewindow("image", WINDOW_AUTOSIZE);
imshow("image", draw);
waitKey();