DCT變換及量化的c++實現(基於opencv矩陣運算)
阿新 • • 發佈:2019-01-01
由於DCT的數學原理不好描述,直接放程式碼了:
執行結果:#include<iostream> #include<fstream> #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> using namespace std; using namespace cv; const double pi = 3.141592; void initDctMat(Mat &A) //計算8x8塊的離散餘弦變換系數 { for (int i = 0; i < 8; ++i) for (int j = 0; j < 8; ++j) { float a; if (i == 0) a = sqrt(1.0 / 8.0); else a = sqrt(2.0 / 8.0); A.ptr<float>(i)[j] = a*cos((j + 0.5)*pi*i / 8); } } //dct變換 void myDct(Mat &image, const Mat &A, const Mat &mask) { //分塊 8x8 for(int i = 0; i < 256; i+=8) for (int j = 0; j < 256; j += 8) { //X = AXAT image(Range(i, i + 8), Range(j, j + 8)) = A * image(Range(i, i + 8), Range(j, j + 8)) *A.t(); //用mask量化 image(Range(i, i + 8), Range(j, j + 8)) /= mask; } } //dct反變換 void myiDct(Mat &image, const Mat &A, const Mat &mask) { //分塊8x8 for (int i = 0; i < 256; i += 8) for (int j = 0; j < 256; j += 8) { //還原量化 image(Range(i, i + 8), Range(j, j + 8)) = image(Range(i, i + 8), Range(j, j + 8)).mul(mask); //X = ATXA image(Range(i, i + 8), Range(j, j + 8)) = A.t() * image(Range(i, i + 8), Range(j, j + 8)) * A; } } int main() { //讀取影象,影象為灰度圖,單通道 Mat image = imread("lena.bmp",CV_LOAD_IMAGE_GRAYSCALE); Mat fimage; Mat A(Size(8, 8), CV_32FC1);// 離散餘弦係數矩陣 //初始化mask量化矩陣 float msk[8][8] = { {16,11,10,16,24,40,51,61},{12,12,14,19,26,58,60,55},{14,13,16,24,40,57,69,56},{14,17,22,29,51,87,80,62},{18,22,37,56,68,109,103,77},{24,35,55,64,81,104,113,92},{49,64,78,87,103,121,120,101},{72,92,95,98,112,100,103,99}}; Mat mask(8, 8, CV_32FC1, msk); //顯示原圖 if (!image.empty()) imshow("image", image); //計算A係數 initDctMat(A); //轉換成浮點數矩陣,進行dct變換 image.convertTo(fimage, CV_32FC1); myDct(fimage, A, mask); //計算壓縮率, 用非零矩陣點數量比總數量、 fimage.convertTo(image, CV_8UC1); double dctRate = countNonZero(image) / (256.0 * 256.0); cout << "the size becomes " << dctRate * 100 << "% of the original." << endl; imshow("壓縮圖", fimage); //dct反變換 myiDct(fimage, A, mask); //顯示還原的影象 fimage.convertTo(image, CV_8UC1); imshow("還原圖", image); waitKey(0); return 0; }