특정 색상 영역 추출하기

강형우·2022년 12월 6일
0

OpenCV

목록 보기
16/17
post-thumbnail

색상 범위 지정

색상 범위 지정

  • RGB, HSV, YCrCb등의 색 공간에서 각 색상 성분의 범위를 지정하여 특정 색상 영역 추출하기

  • 조명이 좀 더 밝아지거나 어두워졌을때는 RGB보단 HSV가 조명 밝기의 영향을 덜 받는 좀 더 stable하다.
  • 범위 선택 함수
void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst);
  • src: 입력행렬
  • lowerb: 하한 값(Mat 또는 Scalar)
  • upperb: 상한 값(Mat 또는 Scalar)
  • dst: 입력 영상과 동일 크기. CV_8UC1. 범위 안에 들어가는 픽셀 값만 255로 설정됨.
  • 색상 범위 지정 기능을 이용한 컬러 필터 만들기
    • 입력 컬러 영상에서 특정 색상 영역은 그대로 유지하고, 나머지 영역은 그레이스케일 형식으로 변환하는 효과 구현하기
  • 영상에서 특정 색상을 제외한 나머지 부분만 그레이스케일로 변환
    • inRange() 함수로 마스크 영상 생성
    • 마스크 영상을 지정하여 copyTo()함수 수행
#include <iostream>
#include <algorithm>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int pos_hue1 = 50, pos_hue2 = 80, pos_sat1 = 150, pos_sat2 = 255;
Mat src, src_hsv, dst, mask;

void on_hsv_changed(int, void*)
{
	Scalar lowerb(pos_hue1, pos_sat1, 0);
	Scalar upperb(pos_hue2, pos_sat2, 255);
	inRange(src_hsv, lowerb, upperb, mask);

	cvtColor(src, dst, COLOR_BGR2GRAY);
	cvtColor(dst, dst, COLOR_GRAY2BGR);
	src.copyTo(dst, mask);

	imshow("mask", mask);
	imshow("dst", dst);
}

int main()
{
	src = imread("candies.png", IMREAD_COLOR);
	cvtColor(src, src_hsv, COLOR_BGR2HSV);

	namedWindow("src");
	namedWindow("mask");
	namedWindow("dst");

	imshow("src", src);

	createTrackbar("Lower Hue", "dst", &pos_hue1, 179, on_hsv_changed);
	createTrackbar("Upper Hue", "dst", &pos_hue2, 179, on_hsv_changed);
	createTrackbar("Lower Sat", "dst", &pos_sat1, 255, on_hsv_changed);
	createTrackbar("Upper Sat", "dst", &pos_sat2, 255, on_hsv_changed);
	on_hsv_changed(0, 0);

	waitKey();
}
  • 실행 결과

히스토그램 역투영

히스토그램 역투영

  • 히스토그램 역투영(histogram backprojection)
    • 주어진 히스토그램 모델에 영상의 픽셀들이 얼마나 일치하는지를 검사하는 방법
    • 임의의 색상 영역을 검출할 때 효과적
    • 조명의 밝기 변화의 영향을 줄이기 위해 보통 HSV 색 공간에서 HS성분만 사용하거나, YCrCb 색 공간에서 CrCb 성분만 사용
  • 마우스로 선택한 영역과 유사한 색상 영역을 검출하는 예제
  • 예제 프로그램
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	// Calculate CrCb histogram from a reference image

	Mat src = imread("cropland.png", IMREAD_COLOR);
	Rect rc = selectROI(src);

	Mat src_ycrcb;
	cvtColor(src, src_ycrcb, COLOR_BGR2YCrCb);

	Mat crop = src_ycrcb(rc);

	Mat hist;
	int channels[] = {1, 2};
	int cr_bins = 128; int cb_bins = 128;
	int histSize[] = {cr_bins, cb_bins};
	float cr_range[] = {0, 256};
	float cb_range[] = {0, 256};
	const float* ranges[] = {cr_range, cb_range};

	// 부분 영상에 대한 히스토그램 계산
	calcHist(&crop, 1, channels, Mat(), hist, 2, histSize, ranges);
	
	// 전체 영상에 대해 히스토그램 역투영
	Mat backproj;
	calcBackProject(&src_ycrcb, 1, channels, hist, backproj, ranges);

	Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3);
	src.copyTo(dst, backproj);

	//imshow("src", src);
	imshow("dst", dst);
	waitKey();
}
  • 실행 결과
  • 히스토그램 역투영 함수
    void calcBackProject(const Mat* images, int nimages, const int* channels, InputArray hist, OutputArray backProject, const float** ranges,
    double scale = 1, bool uniform = true);
    • images: 입력 영상 주소 (또는 입력 영상 배열 주소)
    • nimages: 입력 영상 개수
    • channels: 입력 히스토그램
    • backProject: (출력) 히스토그램 역투영 결과 행렬. 입력 영상과 동일 크기, CV_8U. 발생 빈도가 높으면 원소 값이 크게 나타남.
    • ranges: 히스토그램 빈 경계값 배열의 배열
  • 히스토그램 역투영을 이용한 살색 검출
    1) 기준 영상으로부터 살색에 대한 컬러 히스토그램을 미리 계산

    2) 입력 영상에서 미리 구한 살색 히스토그램에 부합하는 픽셀을 선별
  • 히스토그램 역투영을 이용한 살색 검출 예제
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	// Calculate CrCb histogram from a reference image

	Mat ref, ref_ycrcb, mask;
	ref = imread("ref.png", IMREAD_COLOR);
	mask = imread("mask.bmp", IMREAD_GRAYSCALE);
	cvtColor(ref, ref_ycrcb, COLOR_BGR2YCrCb);

	Mat hist;
	int channels[] = { 1, 2 };
	int cr_bins = 128; int cb_bins = 128;
	int histSize[] = { cr_bins, cb_bins };
	float cr_range[] = { 0, 256 };
	float cb_range[] = { 0, 256 };
	const float* ranges[] = { cr_range, cb_range };

	calcHist(&ref_ycrcb, 1, channels, mask, hist, 2, histSize, ranges);
...
  • 실행 결과
    (가우시안 블러 처리 전)

    (가우시안 블러 처리 후)

0개의 댓글