- 영상에 라플라시간을 거친 결과를 빼면 영상 에지가 두드러지게 돼 선명한 영상이 됨.
- sharpened_pixel = 5*current-left-right-up-down;
- current는 가운데, left는 바로 현재 한 행의 왼쪽의 화소, up은 이전 줄의 가운데에 대응 하는 화소이다.
- Example
#include <iostream>#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
void sharpen(const cv::Mat &image, cv::Mat &result){
result.create(image.size(), image.type());
// 필요하면 할당
// create는 원본의 사이즈와 타입을 똑같이 만들어줌
for(int j=1 ; j<image.rows-1 ; j++){ // 모든 행에 대해(처음과 마지막을 제외하고)
const uchar* previous = image.ptr<const uchar>(j-1); // 이전 행
const uchar* current = image.ptr<const uchar>(j); // 현재 행
const uchar* next = image.ptr<const uchar>(j+1); // 다음 행
uchar* output = result.ptr<uchar>(j); // 결과 행
for(int i=1 ; i<image.cols-1 ; i++){
*output++ = cv::saturate_cast<uchar>(5*current[i] + current[i-1] - current[i+1] - previous[i] - next[i]);
output[i]= cv::saturate_cast<uchar>(5*current[i]-current[i-1]-current[i+1]-previous[i]-next[i]);
}
}
// 처리하지 않는 화소를 0으로 설정
result.row(0).setTo(cv::Scalar(0));
result.row(result.rows-1).setTo(cv::Scalar(0));
result.col(0).setTo(cv::Scalar(0));
result.col(result.cols-1).setTo(cv::Scalar(0));
}
int main()
{
cv::Mat image = cv::imread("img2.jpg", 0);
cv::Mat result;
sharpen(image, result);
cv::namedWindow("Image");
cv::imshow("Image", image);
cv::namedWindow("Result");
cv::imshow("Result", result);
cv::waitKey(5000);
return 0;
}
- Result
- 예제 분석
- 이전 행과 다음 행의 이웃 화소에 접근하려면 다른 하나에 대해서 간단히 포인터를 추가해 정의하며 서로 결합해 증가한다.- cv::staturate_cast는 0이하 255미만이라는 화소값 허용 범위를 벗어나는 경우가 종종 있다.
- cv::staturate_cast<uchar>함수를 이용해서 음수 값을 0으로, 255 이상 값을 255로 변환한다.
- 이웃을 완전히 정의하지 않았기 때문에 테두리 화소를 처리할 수 없어서 별도로 다뤄야하며, 여기서는 0으로 설정한다.
- row와 col 메소드를 사용해 테두리 화소를 0으로 설정.
- setTo : 모든 행렬 요소에 대한 값을 할당.
- result.row(0).setTo(cv::Scalar(0)); // 영상의 첫 번째 행에 있는 모든 화소에 0을 할당
- 3채널 컬러 영상이면 각 채널 화소에 할당하는 세 가지 값을 지정하는 cv::Scalar(a, b, c) 사용.
- 참고문헌 : OpenCV 2 Computer Vision Application Programming Cookbook