티스토리 뷰

원본 코드
https://github.com/opencv/opencv/blob/master/samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp

원문 설명
https://docs.opencv.org/3.1.0/d7/d37/tutorial_mat_mask_operations.html

border 설명
https://docs.opencv.org/3.4.0/dc/da3/tutorial_copyMakeBorder.html

`

#include <opencv2/imgcodecs.hpp>

#include <opencv2/highgui.hpp>

#include <opencv2/imgproc.hpp>

#include
using namespace std;
using namespace cv;

String filename = "/opecvImage/j11.jpg";

void Sharpen(const Mat& myImage,Mat& Result);

//커널 행렬 곱하기를 두가지 방법으로 수행한다.
//
//커널 행렬을 정의하고, filter2D함수로 수행.
//행렬 곱하는 함수를 직접 만들어서 수행.

int main( int argc, char* argv[])
{
Mat src, dst0, dst1;
src = imread( filename, IMREAD_GRAYSCALE);

//파일이 없는 경우.
if (src.empty())
{
cerr << "Can't open image [" << filename << "]" << endl;
return -1;
}

//윈도우 생성.
namedWindow("Input", WINDOW_AUTOSIZE);
namedWindow("Output", WINDOW_AUTOSIZE);

double t = (double)getTickCount();

//샤픈 연산.
Sharpen( src, dst0 );

//윈도우1 보여주기.
imshow( "Input", dst0 );

//Sharpen( dst0, dst0 );
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Hand written function time passed in seconds: " << t << endl;
imshow( "Output", dst0 );

waitKey();

//커널 행렬 정의
Mat kernel = (Mat_(3,3) <<
0,-1,0,
-1,4,-1,
0,-1,0);

//
t = (double)getTickCount();

// 커널 행렬 곱함. (인풋, 아웃풋, 뎁스?, 커널)
// src에 kernel을 곱한 결과를 dst0에 저장한다.
filter2D( src, dst0, src.depth(), kernel );

//int cv::Mat::depth()
//depth() returns the depth of a matrix element. such as CV_8U.

t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Built-in filter2D time passed in seconds: " << t << endl;

imshow( "Output", dst0);

waitKey();
return 0;
}

//커널 행렬 곱한것과 같은 효과.
//입력변수가 Mat의 주소이므로, 해당 주소의 Mat값을 직접 변경할 수 있다.(call by reference)
void Sharpen(const Mat& myImage, Mat& Result)
{
CV_Assert(myImage.depth() == CV_8U); // accept only uchar images
Result.create(myImage.size(), myImage.type());
const int nChannels = myImage.channels();

//각 픽셀에 커널 곱하기
for(int j = 1; j < myImage.rows - 1; ++j)
{
const uchar* previous = myImage.ptr(j - 1);
const uchar* current = myImage.ptr(j );
const uchar* next = myImage.ptr(j + 1);
uchar* output = Result.ptr(j);
for(int i = nChannels; i < nChannels * (myImage.cols - 1); ++i)
{
*output++ = saturate_cast(5 * current[i]
-current[i - nChannels] - current[i + nChannels] - previous[i] - next[i]);
}
}

//경계에 해당하는 값을 0으로
//(참고)imread를 통해 불러온 값은 기본으로 크기1인 border를 갖는다.
//(참고)border를 추가할수도 잇다. copyMakeBorder()함수
Result.row(0).setTo(Scalar(0));
Result.row(Result.rows - 1).setTo(Scalar(0));
Result.col(0).setTo(Scalar(0));
Result.col(Result.cols - 1).setTo(Scalar(0));
}

`

반응형
댓글