利用拉普拉斯算子進行圖像銳化是數字圖像處理里比較簡單的處理手段,下面的例子參考opencv 2 computer vision application programming cookbook,采用兩種方法對輸入圖像進行拉普拉斯銳化,原理比較簡單,故不贅述了。
編譯環境:VS2010+OpenCV2.3.1
編程細節:
- 函數的形參表中,為了防止修改輸入圖像image,故形參傳遞為pass by conference-const,同時函數體中指向輸入圖像的指針也必須聲明為指向const對象的指針,如const uchar *next = image.ptr<const uchar>(j);
- cv::Mat::row()返回由單行或者單列組成的特定的cv::Mat實例,cv::Scalar(a,b,c)指定每個通道的特定值;
- 第二種方法中,利用函數cv::filter2D(),需先創建一個核cv::Mat,並對核進行初始化。
code:
1 /*************************************************************** 2 * 3 * 內容摘要:分別用兩種方法對輸入圖像進行拉普拉斯算子銳化,並比較 4 * 兩種方法的執行效率,從運行結果來看,第二種方法的效率 5 * 更高。 6 * 作 者:劉軍(Jacky Liu) 7 * 完成日期:2012.8.12 8 * 參考資料:opencv 2 computer vision application programming 9 * cookbook 10 * 11 ***************************************************************/ 12 13 #include <opencv2/core/core.hpp> 14 #include <opencv2/highgui/highgui.hpp> 15 #include <opencv2/imgproc/imgproc.hpp> 16 #include <iostream> 17 18 //輸入形參為pass by conference-const,保證輸入的圖像不會被修改,並且為傳遞引用 19 void sharpenImage0(const cv::Mat &image, cv::Mat &result) 20 { 21 //為輸出圖像分配內存 22 result.create(image.size(),image.type()); 23 24 /*濾波核為拉普拉斯核3x3: 25 0 -1 0 26 -1 5 -1 27 0 -1 0 28 */ 29 for(int j= 1; j<image.rows-1; ++j) 30 { 31 const uchar *previous = image.ptr<const uchar>(j-1); 32 const uchar *current = image.ptr<const uchar>(j); 33 const uchar *next = image.ptr<const uchar>(j+1); 34 uchar *output = result.ptr<uchar>(j); 35 for(int i= 1; i<image.cols-1; ++i) 36 { 37 *output++ = cv::saturate_cast<uchar>(5*current[i]-previous[i]-next[i]-current[i-1]-current[i+1]); //saturate_cast<uchar>()保證結果在uchar范圍內 38 } 39 } 40 result.row(0).setTo(cv::Scalar(0)); 41 result.row(result.rows-1).setTo(cv::Scalar(0)); 42 result.col(0).setTo(cv::Scalar(0)); 43 result.col(result.cols-1).setTo(cv::Scalar(0)); 44 } 45 46 void sharpenImage1(const cv::Mat &image, cv::Mat &result) 47 { 48 //創建並初始化濾波模板 49 cv::Mat kernel(3,3,CV_32F,cv::Scalar(0)); 50 kernel.at<float>(1,1) = 5.0; 51 kernel.at<float>(0,1) = -1.0; 52 kernel.at<float>(1,0) = -1.0; 53 kernel.at<float>(1,2) = -1.0; 54 kernel.at<float>(2,1) = -1.0; 55 56 result.create(image.size(),image.type()); 57 58 //對圖像進行濾波 59 cv::filter2D(image,result,image.depth(),kernel); 60 } 61 62 int main(int argc, char* argv[]) 63 { 64 cv::Mat image = cv::imread("../boldt.jpg"); 65 cv::Mat image_gray; 66 image_gray.create(image.size(),image.type()); 67 68 if(!image.data) 69 return -1; 70 if(image.channels() == 3) 71 cv::cvtColor(image,image_gray,CV_RGB2GRAY); 72 73 cv::Mat result; 74 result.create(image_gray.size(),image_gray.type()); 75 double time_ = static_cast<double>(cv::getTickCount()); 76 sharpenImage0(image_gray,result); 77 time_ = 1000*(static_cast<double>(cv::getTickCount())-time_)/cv::getTickFrequency(); 78 std::cout<<"time = "<<time_<<"ms"<<std::endl; 79 80 cv::namedWindow("Image 1"); 81 cv::imshow("Image 1",result); 82 83 cv::Mat result1; 84 result1.create(image_gray.size(),image_gray.type()); 85 time_ = static_cast<double>(cv::getTickCount()); 86 sharpenImage1(image_gray,result1); 87 time_ = 1000*static_cast<double>(cv::getTickCount()-time_)/cv::getTickFrequency(); 88 std::cout<<"time = "<<time_<<"ms"<<std::endl; 89 90 cv::namedWindow("Image 2"); 91 cv::imshow("Image 2",result1); 92 93 cv::waitKey(); 94 return 0; 95 }
運行結果:從運行結果來看,兩種方法得出的效果基本一樣。