레이블이 OpenCV인 게시물을 표시합니다. 모든 게시물 표시
레이블이 OpenCV인 게시물을 표시합니다. 모든 게시물 표시

2015년 9월 26일 토요일

OpenCV - 같은 그림 찾기 - compareHist

matchTemplate을 사용하면 같은 그림을 찾을 수 있다. 하지만 단점이 있는데 모양이 비슷한 것은 비슷한 결과를 돌려 준다. 즉, 정확도가 떨어진다.

그림을 찾는 또 다른 방법으로 compareHist가 있다. compareHist는 히스토그램이 얼마나 같은지 비교해 준다. 즉, 색상분포가 얼마나 비슷한지를 알 수 있다. 하지만 색상분포만 같은 것으로 같은 그림이라고 할 수 없기 때문에 matchTemplate가 함께 사용하면 99%이상 동일한 그림을 찾을 수 있다.

히스토그램은 명도에 상관없이 계산되는 것이 바람직하다. 따라서 HSV로 변환한 뒤 Hue(색조)와 Saturation(채도)에 대해서만 계산하도록 한다.


cvtColor

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 )

src를 code로 지정된 형식으로 변환해서 dst로 돌려 준다. HSV로 변환할 때 CV_BGR2HSV를 지정한다.


calcHist

void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )

images로 지정된 이미지에서 히스토그램을 계산해서 hist로 돌려준다. HSV이미지 한개를 지정할때 nimages는 1, channels는 {0, 1}, mask는 사용하지 않도록 Mat()를 지정한다.

dims : 히스토그램 갯수, HS를 지정한 경우 2
histSize : 각 히스토그램의  크기를 배열로 지정한다. HS을 각각 60으로 지정하는 경우 {60, 60}
ranges : 히스토그램 범위, H는 {0,180}, S는 {0,256}
uniform : true
accumulate : false


compareHist

double compareHist(InputArray H1, InputArray H2, int method)

히스토그램 H1과 H2를 비교해서 결과를 돌려 준다.


http://docs.opencv.org/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.html

OpenCV - 같은 그림 찾기 - matchTemplate

아래 그림처럼 개들이 잔뜩 있는 곳에서 강아지 한마리를 찾아 내려면 어떻게 해야 할까.

 방법은 강아지 그림을 움직여 가면서 비교해 보면 된다.

왼쪽에서 오른쪽으로 그리고 위에서 아래쪽으로 한 픽셀씩 움직이면서 각 픽셀의 빼기나 곱하기 계산을 한다. 그 결과를 배열로 저장해서 보면 아래 그림처럼 가장 값이 큰(밝은) 부분이 가장 가능성이 높은 부분임을 알 수 있다.





matchTemplate

void matchTemplate(InputArray image, InputArray templ, OutputArray result, int method)

image안에서 x, y로 한칸씩 이동하면서 templ을 겹쳐 놓고 각 셀의 차이나 곱의 합을 계산해서 result배열을 만들어서 돌려 준다. 이때 image의 크기는 templ의 크기보다 커야 하고 계산 방식은 method로 정해진다.

CV_TM_SQDIFF ... 각 픽셀의 차이의 합
CV_TM_SQDIFF_NORMED ... CV_TM_SQDIFF / sqrt(각 픽셀의 제곱의 곱)
CV_TM_CCORR ... 각 픽셀의 곱의 합
CV_TM_CCORR_NORMED ... CV_TM_CCORR / sqrt(각 픽셀의 제곱의 곱)
CV_TM_CCOEFF
CV_TM_CCOEFF_NORMED ... CV_TM_CCOEFF / sqrt(각 픽셀의 제곱의 곱)


normalize

void normalize(InputArray src, OutputArray dst, double alpha=1, double beta=0, int norm_type=NORM_L2, intdtype=-1, InputArray mask=noArray() )

normType=NORM_MINMAX일때 src를 alpha(최소값)과 beta(최대값) 사이의 값으로 환산한다.


minMaxLoc

void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArraymask=noArray())

src배열에서 최소와 최대값을 찾은 후 그 값과 위치를 돌려 준다.


http://stackoverflow.com/questions/11541154/checking-images-for-similarity-with-opencv
http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html

2015년 2월 20일 금요일

OpenCV - 콘트라스트와 밝기 적용하기

콘트라스트와 밝기는 아래 수식으로 표현된다.
g(x) = \alpha f(x) + \beta

알파는 0보다 큰 콘트라스트 값이다. 베타는 밝기값이다. 는 입력이미지이고 는 출력이미지이다. 정확하게는 아래와 같이 표현할 수 있다.

g(i,j) = \alpha \cdot f(i,j) + \beta

여기에서 i는 이미지에서 x축을 의미하고 j는 y축을 의미한다. 이 함수의 샘플코드는 아래와 같다.


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

using namespace cv;

double alpha; /*< Simple contrast control */
int beta;  /*< Simple brightness control */

int main( int argc, char** argv )
{
   /// Read image given by user
   Mat image = imread( argv[1] );
   Mat new_image = Mat::zeros( image.size(), image.type() );

   /// Initialize values
   std::cout<<" Basic Linear Transforms "<<std::endl;
   std::cout<<"-------------------------"<<std::endl;
   std::cout<<"* Enter the alpha value [1.0-3.0]: ";std::cin>>alpha;
   std::cout<<"* Enter the beta value [0-100]: "; std::cin>>beta;

   /// Do the operation new_image(i,j) = alpha*image(i,j) + beta
   for( int y = 0; y < image.rows; y++ ) {
       for( int x = 0; x < image.cols; x++ ) {
           for( int c = 0; c < 3; c++ ) {
               new_image.at<Vec3b>(y,x)[c] =
               saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta );
           }
       }
   }

   /// Create Windows
   namedWindow("Original Image", 1);
   namedWindow("New Image", 1);

   /// Show stuff
   imshow("Original Image", image);
   imshow("New Image", new_image);

   /// Wait until user press some key
   waitKey();
   return 0;
}



gray scale이미지일때는 채널(RGB)이 없으므로 아래와 같이 변경되어야 한다.

   for( int y = 0; y < image.rows; y++ ) {
       for( int x = 0; x < image.cols; x++ ) {
           new_image.at<uchar>(y,x) =
           saturate_cast<uchar>( alpha*( image.at<uchar>(y,x) ) + beta );
       }
   }


saturate_cast함수는 대상수치가 지정된 데이터형의 최소값 밑으로 내려간 경우 데이터형의 최소값을 돌려 주고 최대값을 넘어 간 경우 최대값을 돌려 주는 함수다. 즉, 보통 데이터 형이 바뀌면서 표현할 수 있는 비트가 줄어 드는 경우 상위비트를 버리고 하위비트만을 취하면서 이상한 값을 돌려 주는 문제가 발생하는데 saturate_cast는 이런 문제를 해결하기 위한 것이다.


참고링크

http://docs.opencv.org/trunk/doc/tutorials/core/basic_linear_transform/basic_linear_transform.html

OpenCV - 기본적인 이미지 처리 함수


Include에 사용된 파일
실행시에 필요한 DLL파일
#include <opencv2/core/core.hpp>
OpenCV\build\x86\vc11\bin\opencv_core248.dll
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/imgproc/imgproc.hpp"
OpenCV\build\x86\vc11\bin\opencv_imgproc248.dll
#include <opencv2/highgui/highgui.hpp>
OpenCV\build\x86\vc11\bin\opencv_highgui248.dll


OpenCV의 namespace

    using namespace cv;

이미지파일을 읽는 방법

    Mat image;
    image = imread(argv[1], IMREAD_COLOR); // Read the file

imread함수는 첫번째 지정된 파일을 두번째 지정된 형식으로 읽어 들인다. 이때 색상은 RGB순서가 아니고 BGR순서로 저장된다.


특정 범위에 있는 색상을 바꾸는 방법

    // Red를 Green으로 바꾸는 예
    Vec3b upper = Vec3b(0, 0, 255); //B, G, R
    Vec3b lower = Vec3b(0, 0, 255);
    Vec3b with = Vec3b(0, 255, 0);
    Mat mask;

    inRange(image, lower, upper, mask);
    image.setTo(with, mask);

inRange함수는 image에 있는 색상 중 lower이상이고 upper이하인 색상에 대한 마스크를 만들어 mask에 저장해서 돌려 준다. 이때 RGB 세개를 한꺼번에 비교하는 것이 아니라 R이 범위에 들어가는지, G가 범위에 들어 가는지, B가 범위에 들어 가는지 각각 따로 비교해서 모두 범위에 들어 가는 것만 mask대상이 된다.


Mat.setTo함수는 이미지에 있는 색상 중에서 mask로 지정된 부분에 있는 색상을 with로 대체한다.

컬러 이미지를 그레이로 바꾸는 방법

    Mat mat_gray;
    cv::cvtColor(image, mat_gray, CV_BGR2GRAY);

cvtColor함수는 첫번째 인수로 지정된 이미지를 세번째 인수형식으로 바꾼 이미지를 두번째 인수로 돌려 준다.

이미지 크기를 바꾸는 방법

    double factor = 3.0;
    Mat mat_sized;
    int width = (int)(mat_gray.size().width * factor);
    int height =  (int)(mat_gray.size().height * factor);
    cv::resize(mat_gray, mat_sized, Size(width, height));
resize함수는 첫번째 인수로 지정된 이미지를 세번째 크기로 바꾼 이미지를 두번째 인수로 돌려 준다.

이미지파일 저장

    cv::imwrite( filename, mat_sized);


OpenCV - Visual Studio 2012 설정하는 방법

OpenCV는 영상 또는 그래픽처리에 필요한 각종 알고리즘을 구현한 라이브러리로서 C++, C, Python과 Java용 인터페이스를 갖고 있고 Windows, Linux, Mac OS, iOS와 Android를 지원한다.

Windows용 라이브러리 설치하는 방법

1. Windows용 OpenCV를 다운로드 한 후 압축을 푼다.

2. OpenCV폴더용 시스템변수를 만든다.

setx -m OPENCV_DIR D:\OpenCV\Build\x86\vc10     (Visual Studio 2010 - 32 bit Windows)
setx -m OPENCV_DIR D:\OpenCV\Build\x64\vc10     (Visual Studio 2010 - 64 bit Windows)

setx -m OPENCV_DIR D:\OpenCV\Build\x86\vc11     (Visual Studio 2012 - 32 bit Windows)
setx -m OPENCV_DIR D:\OpenCV\Build\x64\vc11     (Visual Studio 2012 - 64 bit Windows)

Visual Studio 2012 설정하는데는 두가지가 필요하다.

  • 컴파일에게 라이브러리가 어떻게 구성되어 있는지 알려 주어야 한다.
  • 링커에게 사용된 함수와 데이터를 어디에서 가져 와야 하는지 알려 주어야 한다.
1. C/C++ ‣ Additional Include Directories지정 ... $(OPENCV_DIR)\..\..\include


2. Linker ‣ General ‣ Additional Library Directories지정 ... $(OPENCV_DIR)\lib


3. Linker ‣ Input ‣ Additional Dependencies지정


opencv_core248.lib

opencv_imgproc248.lib
opencv_highgui248.lib
opencv_ml248.lib
opencv_video248.lib
opencv_features2d248.lib
opencv_calib3d248.lib
opencv_objdetect248.lib
opencv_contrib248.lib
opencv_legacy248.lib
opencv_flann248.lib

파일이름 형식 ... opencv_(모듈이름)(버전번호)(d=디버그용일때).lib