之前幾天搗鼓matlab,用來處理數字圖像,矩陣操作什麼的,如果忘記線性代數就真的GG了。
在用了matlab被深深地吐槽之後,決定改用opencv,C++貌似也是處理數字圖像的很好的工具
1. 在ubuntu上安裝opencv
教程可以百度之,都很詳細的
2. 像素處理圖像:
(1)根據輸入的數據,用鄰近取樣插值法,縮放圖像
鄰近取樣插值法原理:http://blog.chinaunix.net/uid-27675161-id-3452025.html
(2)根據輸入,改變數字圖像的灰度分辨率
(3)此次實驗操作用灰度圖來實現
3. 直接貼代碼+注釋吧
1 //my_hw1.cpp 2 #include <stdio.h> 3 #include<iostream> 4 #include <opencv2/opencv.hpp> 5 #include<opencv2/core/core.hpp> 6 #include<opencv2/highgui/highgui.hpp> 7 8 using namespace cv; 9 using namespace std; 10 11 string my_pic = "07.png"; 12 Mat image = imread(my_pic, CV_LOAD_IMAGE_GRAYSCALE); 13 14 void on_trackbar(int p, void*) { 15 16 //************************Scale*************************** 17 //每次回調都重新載入圖像 18 Mat src = imread(my_pic, CV_LOAD_IMAGE_GRAYSCALE); 19 20 //獲取三個滑動條的值 21 int c = cvGetTrackbarPos("Width", "after change"); 22 int r = cvGetTrackbarPos("Height", "after change"); 23 int level = cvGetTrackbarPos("Level", "after change"); 24 25 //記錄原始圖的寬高,以及對應的點sx,sy(鄰近取樣插值法中用到) 26 int sh = src.rows; 27 int sw = src.cols; 28 int sx, sy; 29 30 //重置後的新圖片 31 Mat dst(r, c, src.type()); 32 33 //填充新圖片的像素 34 for (int i = 0; i < r; i ++) { 35 for (int j = 0; j < c; j ++) { 36 double x = i / (r + 0.0); 37 double y = j / (c + 0.0); 38 sx = sh * x; 39 sy = sw * y; 40 dst.at<uchar>(i, j) = src.at<uchar>(sx,sy); 41 } 42 } 43 44 //********************Quantization************************ 45 46 //使得level的值合法 47 if (level <= 256 && level >= 128)level = 128; 48 else if(level < 128 && level >= 64)level = 64; 49 else if(level < 64 && level >= 32)level = 32; 50 else if(level < 32 && level >= 16) level = 16; 51 else if(level < 16 && level >= 8)level = 8; 52 else if(level < 8 && level >= 4)level = 4; 53 else level = 2; 54 55 int channels = dst.channels(); 56 int nrows = dst.rows; 57 int ncols = dst.cols * channels; 58 59 uchar table[256]; 60 int degree = 255/(level - 1); 61 int number = 256 / level; 62 int count = 0; 63 int value = 0; 64 65 //設定好要求的灰度映射 66 for (int i = 0; i < 256; i ++, count ++) { 67 if (count < number) table[i] = value; 68 else { 69 count = 0; 70 value += degree; 71 table[i] = value; 72 } 73 } 74 75 if (src.isContinuous()) { 76 ncols *= nrows; 77 nrows = 1; 78 } 79 80 for (int i = 0; i < nrows; i ++) { 81 uchar *p = dst.ptr<uchar>(i); 82 for (int j = 0; j < ncols; j ++) { 83 p[j] = table[p[j]]; 84 } 85 } 86 87 //cout << level << " " << c << " " << r << "\n"; 88 imshow("after change", dst); 89 } 90 91 int main( int argc, char** argv) { 92 imshow("before change", image); 93 94 int width = 384; 95 int height = 256; 96 int level = 256; 97 namedWindow("after change", CV_WINDOW_AUTOSIZE); 98 createTrackbar( "Width", "after change", &width, 800, on_trackbar); 99 createTrackbar( "Height", "after change", &height, 500, on_trackbar); 100 createTrackbar( "Level", "after change", &level, 256, on_trackbar); //slider 101 102 on_trackbar(0, 0); 103 104 waitKey(); 105 return 0; 106 } 107
另外,我選擇的編譯方式是cmake + make;
CMakeLists.txt
1 cmake_minimum_required(VERSION 2.8) 2 project( my_hw1 ) 3 find_package( OpenCV REQUIRED ) 4 add_executable( my_hw1 my_hw1.cpp ) 5 target_link_libraries( my_hw1 ${OpenCV_LIBS} ) CMakeLists.txt把相應的圖片放到同目錄的文件夾內,進入到該文件夾,輸入命令行
cmake .
make
./my_hw1
就可以執行了~~
最後貼上一個運行結果圖: