1. Image 결합 

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <array>

using namespace std;

int main() {
	// cv namespace는 설명을 위해 사용하지 않음 
	cv::Mat img = cv::imread("img1.png");
	cv::Mat gray_img;
	cv::cvtColor(img, gray_img, cv::COLOR_BGR2GRAY); // gray.로 변환 

	cout << gray_img.size() << " channel : " << gray_img.channels() << endl; // 225x225x1
	cout << img.size() << " channel : " << img.channels() << endl; // 225x225x3

	array<cv::Mat, 3> arr = { gray_img, gray_img, gray_img };

	cv::Mat merge_img; 
	cv::merge(arr, merge_img); // ArrayOfArray를 합침 
	
	cout << merge_img.size() << " channel : " << merge_img.channels() << endl; //225x225x3

	cv::Mat concat_img;
	cv::hconcat(merge_img, img, concat_img); // 수평으로 결합 - 차원이 같아야함 
	//cv::vconcat(merge_img, img, concat_img); // 수직으로 결합 - 차원이 같아야함 

	cout << concat_img.size() << " channel : " << concat_img.channels() << endl; // 450x225x3

	cv::imshow("qwe", concat_img); 
	cv::waitKey(0);

	return 0;
}

  • Opencv에서 제공하는 concat 함수를 사용하여 이미지를 수직 또는 수평으로 결합할 수 있다 
    - vconcat, hconcat 
  • 흑백이미지와 color 이미지를 결합하기 위해서는 흑백이미지의 경우 채널이 1이기 때문에 먼저 3채널로 만든 뒤 결합하여야 한다. 그때 cv::merge 함수를 사용하여 생성하였다  
  • merge를 사용할 때 흑백 이미지에 대해서 array를 생성한 후 merge 하였는데, vertor를 사용하지 않고 array를 사용한 이유는 우리가 원하는 차원의 개수(3)를 알고있기 때문에 원소의 개수를 지정할 수 있는 array를 사용했다 

2. 외곽선 검출 (https://docs.opencv.org/3.4/df/d0d/tutorial_find_contours.html

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <vector>
#include <array>
#include <iostream>

using namespace std; 

cv::Mat gray_img;
const int max_thresh = 255; // threshold 최댓값 
int thresh = 100;
cv::RNG rng(54321); // Random Number Generator - 랜덤값 생성

void thresh_callback(int, void*);

int main() {
	const char* img_path = "milk.jpg";
	cv::Mat img = cv::imread(img_path); // 이미지 읽어오기

	cv::cvtColor(img, gray_img, cv::COLOR_BGR2GRAY); // gray scale로 변환 

	cv::blur(gray_img, gray_img, cv::Size(3, 3)); // 이미지에 블러 적용 3x3 커널사용

	const char* window_name = "origin"; // 보여줄 윈도우 이름 
	cv::namedWindow(window_name);  // 이미지를 보여줄 윈도우 생성 
	cv::imshow(window_name, img); // 이미지 표현 

	cv::createTrackbar("Canny thresh:", window_name, &thresh, max_thresh, thresh_callback); // 이미지에 수평으로 컨트롤 할 수 있는 바 생성 ( 마지막 파라미터는 onChange 함수로 파라미터를 (int, void*) 형태로 가지고 있어야함 
	thresh_callback(0,0); // trackbar에 따라 외곽선 검출 결과를 보여주는 함수 
	cv::waitKey(0);

	return 0;
}

void thresh_callback(int, void*)
{
	cv::Mat canny_output;
	cv::Canny(gray_img, canny_output, thresh, thresh * 2); // Canny 알고리즘을 이용해서 물체의 엣지(edge)를 검출
	vector<vector<cv::Point> > contours; // Point = {int, int} = vector int가 2개 있는 
	vector<cv::Vec4i> hierarchy; // Vec4i = {int, int, int, int} = vector int가 4개있는 

	cv::findContours(canny_output, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE); // binary 이미지에서 외곽선을 찾는다 

	cv::Mat drawing = cv::Mat::zeros(canny_output.size(), CV_8UC3);

	for (size_t i = 0; i < contours.size(); i++)
	{
		cv::Scalar color = cv::Scalar(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
		cv::drawContours(drawing, contours, (int)i, color, 2, cv::LINE_8, hierarchy, 0);
	}
	imshow("Contours", drawing);
}
  • opencv docs에서 새로운 함수를 알게되었다 
     createTrackbar - 설정한 윈도우에 설정한 변수의 값을 변경할 수 있는 바가 생성된다 
  • Edge 추출시 blur를 활용하여 불필요한 edge가 덜 나오게 할 수 있다. 
  • cv::findContours - 외곽선을 검출한다 
    • (input image, output image, contours, hierarchy, int mode, int method, cv::Point offset=cv::Points())
    • mode 의 종류 
      cv2::RETR_EXTERNAL : 외곽선중 가장 바깥쪽 선만 리턴한다 
      cv2::RETR_LIST : 모든 외곽선을 찾지만 계층관계는 구성하지 않는다 
      cv2::RETR_CCOMP : 모든 외곽선을 찾으며 2단계의 계층관계를 구성한다 
      cv2::RETR_TREE : 모든 외곽선을 찾으며 모든 계층관계를 구성한다 
      여기서 계층이란 검출된 외곽선 안에 있는 또다른 외곽선을 뜻한다 
    • method 의 종류
      cv2::CHAIN_APPROX_NONE : 모든 point를 저장
      cv2::CHAIN_APPROX_SIMPLE : 4개의 point만을 저장하여 메모리를 절약 
      cv2::CHAIN_APPROX_TC89_L1 : Teh_Chin 연결 근사 알고리즘 L1버전을 적용하여 point 개수를 줄임 
      cv2::CHAIN_APPROX_TC89_KCOS : Teh_Chin 연결 근사 알고리즘 KCOS 버전을 적용하여 point 개수를 줄임 
      return 값으로 오는 contours의 shape를 찍어보면 각각 method마다 shape이 다른것을 볼 수 있다.
  • cv::Scalar 를 이용하여 외곽선을 그릴 때마다 다른 색상을 적용 
  • cv::drawContours
  • (InputOutputArray image,
    InputArrayOfArrays contours,
    int contourIdx,
    const cv:Scalar &color,
    int thickness=1, int lineType=8,
    cv::InputArray hierarchy=noArray(),
    int maxLevel = 2147483657,
    cv::Point offset = cv::Point())

+ Recent posts