# include # include # include # include #include #include #include # define N 8 # define PI 3.1415926 using namespace std; using namespace cv; void dct2(Mat& A, Mat& AT, Mat& image, Mat& ); //dct正变换 void f_dct2(Mat& A, Mat& AT, Mat& image); //dct反变换 Mat TMatrix(Mat, int); //转置矩阵 Mat dctmtx(int n); //返回N×N的DCT变换矩阵 Mat compression(int,int,Mat image); //图像单通道压缩函数 int main() { int i, j; vector<Mat>channels; //Opencv读入图片,分别用于压缩和比较 Mat Image = imread("bottle477.jpg"); Mat ori_Image = imread("bottle477.jpg"); Image.convertTo(Image, CV_64F); //分离彩色通道 split(Image, channels); Mat imageBlueChannel = channels.at(0); Mat imageGreenChannel = channels.at(1); Mat imageRedChannel = channels.at(2); merge(channels, Image); //R,G,B三通道分别进行压缩 Mat B = compression(Image.cols, Image.rows,imageBlueChannel); Mat G = compression(Image.cols, Image.rows,imageGreenChannel); Mat R = compression(Image.cols, Image.rows,imageRedChannel); //三通道合并 channels.at(0) = Mat_<uchar>(B); channels.at(1) = Mat_<uchar>(G); channels.at(2) = Mat_<uchar>(R); merge(channels, Image); imshow("DstImage",Image); imshow("OriImage", ori_Image); waitKey(0); return 0; } Mat compression(int r, int c, Mat image) { Mat A = dctmtx(N); Mat AT = TMatrix(A, N); //Mask定义 Mat Mask = (Mat_<double>(N, N) << 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
//DCT变换和Mask矩阵量化 dct2(A, AT, image, Mask); //DCT逆变换 f_dct2(A, AT, image); return image; } //生成转换矩阵 Mat dctmtx(int num) { int i, j; //初始化矩阵,定义矩阵 Mat A = Mat::zeros(N, N, CV_64F); //按照公式,生成正交矩阵A double x0 = sqrt(1.0 / num); double x1 = sqrt(2.0 / num); for (i = 0; i < N; ++i) { for (j = 0; j < N; ++j) { if (i == 0) { A.at<double>(i,j) = x0 * cos((2 * j + 1) * PI * i / (2 * N)); } else { A.at<double>(i, j) = x1 * cos((2 * j + 1) * PI * i / (2 * N)); } } } return A; } //矩阵转置 Mat TMatrix(Mat A, int n) { int i, j; Mat tmp; tmp = Mat::zeros(A.size(), A.type()); for (j = 0; j < n; ++j) for (i = 0; i < n; ++i) tmp.at<double>(i, j) = A.at<double>(j, i); return tmp; } //DCT变换 void dct2(Mat& A,Mat& AT, Mat& image, Mat& mask) { for (int i = 0; i < (image.rows - image.rows % N); i += N) { for (int j = 0; j < (image.cols - image.cols % N); j += N) { image(Range(i, i + N), Range(j, j + N)) = A * image(Range(i, i + N), Range(j, j + N)) * AT; image(Range(i, i + N), Range(j, j + N)) = mask.mul(image(Range(i, i + N), Range(j, j + N))); } } } //DCT逆变换 void f_dct2(Mat& A, Mat& AT, Mat& image) { for (int i = 0; i < (image.rows - image.rows % N); i += N) { for (int j = 0; j < (image.cols - image.cols % N); j += N) { image(Range(i, i + N), Range(j, j + N)) = AT * image(Range(i, i + N), Range(j, j + N)) * A; } } } |