是老師布置的作業(yè),拖到ddl才開始,opencv也才剛接觸,有自己結(jié)合百度的一點理解,如有誤,請諒解!
站在用戶的角度思考問題,與客戶深入溝通,找到牙克石網(wǎng)站設(shè)計與牙克石網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:網(wǎng)站設(shè)計、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、主機域名、網(wǎng)頁空間、企業(yè)郵箱。業(yè)務(wù)覆蓋牙克石地區(qū)。DCT圖像壓縮先貼一段在matlab上實現(xiàn)的代碼,這個在網(wǎng)上都可以查到,就不贅述了
I=imread('cameraman.tif');
I=im2double(I);%將圖像轉(zhuǎn)換為雙精度
T=dctmtx(8);% 返回8*8的DCT變換矩陣
B=blkproc(I,[8 8],'P1*x*P2',T,T');
% x就是每一個分成的8*8大小的塊,P1*x*P2相當于像素塊的處理函數(shù),p1=T p2=T’,
%也就是fun=p1*x*p2'=T*x*T'的功能是進行離散余弦變換
mask= [1 1 1 1 0 0 0 0
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];% 保留左上角十個系數(shù)
B2=blkproc(B,[8 8],'P1.*x',mask);%舍棄每個塊中的高頻系數(shù),達到圖像壓縮的目的
I2=blkproc(B2,[8 8],'P1*x*P2',T',T); %進行反余弦變換,得到壓縮后的圖象
figure(1);
subplot(1,4,1),imshow(I);
subplot(1,4,2),imshow(B);
subplot(1,4,3),imshow(B2);
subplot(1,4,4),imshow(I2);
Z = imabsdiff(I,I2);
figure(2);
imshow(Z);
思路如下:
先劃分處理塊大小,對每個塊分別進行DCT變換,再舍棄每個塊中的高頻系數(shù),再進行反余弦變換,得到壓縮圖像(即先使用DCT函數(shù)將低頻的點都集中在左上角,再對右下角的高頻數(shù)據(jù)丟棄)
老師要求我們用c++ + opencv實現(xiàn)。配置環(huán)境真的是。。。。
試過用clion和vscode配,失敗了,還是老老實實用vs2019吧。
附 大佬配置的視頻,十分感謝!
https://www.bilibili.com/video/BV1mE411P76Mp=1&vd_source=393e209b3fa00543c23db5753b265d30
下面是用c++ 實現(xiàn)的代碼 RGB圖(下面有灰度圖,其實差不多)#include
#includeusing namespace cv;
using namespace std;
double T = 100;
int main()
{
Mat src = imread("D:\\Matlab\\toolbox\\images\\imdata\\kids.tif");//先讀入圖像,在這里讀入的是RGB圖像,有三個通道
imshow("clock", src);//先顯示圖像
int big;
big = 8;//定義一下掩蓋矩陣的大小
vectormv;
split(src, mv);//通道分割
Mat b = Mat_(mv[0]);
Mat g = Mat_(mv[1]);
Mat r = Mat_(mv[2]);
b.convertTo(b, CV_32F, 1.0 / 255);
g.convertTo(g, CV_32F, 1.0 / 255);
r.convertTo(r, CV_32F, 1.0 / 255);
//要進行DCT變換先轉(zhuǎn)換成float,我也不知道為什么
Mat bDCT = Mat_(b); //這里先復(fù)制矩陣,后面有用
Mat gDCT = Mat_(g);
Mat rDCT = Mat_(r);
int w = b.rows;
int h = b.cols;//三個通道的大小都是一樣的,所以只要取一個就好了
//DCT變換每個通道都做一遍
for (int i1 = 0; i1< (h / big); i1++) {//注意這里的取值和我們平常遇到的x,y不一樣 一張寬度x像素、高度y像素的灰度圖保存在一個y * x的矩陣中。
for (int j1 = 0; j1< (w / big); j1++) {
dct(b(Rect(i1 * big, j1 * big, big, big)), bDCT(Rect(i1 * big, j1 * big, big, big)));//Rect是滑塊函數(shù),從指定位置取指定大小的矩陣,這就是跟Matlab分塊處理一樣
}
}
//發(fā)現(xiàn)有的圖像不是長寬相同的,所以取整除,而沒有取到數(shù)據(jù),跟之前相同就行了,復(fù)制的用處就來啦
for (int i1 = 0; i1< (h / big); i1++) {
for (int j1 = 0; j1< (w / big); j1++) {
dct(g(Rect(i1 * big, j1 * big, big, big)), gDCT(Rect(i1 * big, j1 * big, big, big)));
}
}
for (int i1 = 0; i1< (h / big); i1++) {
for (int j1 = 0; j1< (w / big); j1++) {
dct(r(Rect(i1 * big, j1 * big, big, big)), rDCT(Rect(i1 * big, j1 * big, big, big)));
}
}
int mask[8][8] = {//定義掩蓋矩陣
{1, 1, 1, 1, 0, 0, 0, 0},
{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},
};
//根據(jù)mask 矩陣 去掉右下角的數(shù)據(jù),同樣對每個通道做一次
for (int i1 = 0; i1< (bDCT.rows / big); i1++)
{
for (int j1 = 0; j1< (bDCT.cols / big); j1++)
{
for (int i = 0; i< big; i++)
{
for (int j = 0; j< big; j++)
{
if (mask[i % big][j % big] == 0)
{
bDCT.at(i1 * big + i, j1 * big + j) = 0;//這里和mask矩陣相乘是同一個意思,同時掃描mask和DCT變換后的矩陣,當mask矩陣掃描到的值為0時,把DCT矩陣也置零,去掉高頻數(shù)據(jù)
}
}
}
}
}
for (int i1 = 0; i1< (gDCT.rows / big); i1++)
{
for (int j1 = 0; j1< (gDCT.cols / big); j1++)
{
for (int i = 0; i< big; i++)
{
for (int j = 0; j< big; j++)
{
if (mask[i % big][j % big] == 0)
{
gDCT.at(i1 * big + i, j1 * big + j) = 0;;
}
}
}
}
} for (int i1 = 0; i1< (rDCT.rows / big); i1++)
{
for (int j1 = 0; j1< (rDCT.cols / big); j1++)
{
for (int i = 0; i< big; i++)
{
for (int j = 0; j< big; j++)
{
if (mask[i % big][j % big] == 0)
{
rDCT.at(i1 * big + i, j1 * big + j) = 0;;
}
}
}
}
}
Mat iDctb = bDCT;
Mat iDctg = gDCT;
Mat iDctr = rDCT;
//進行逆DCT變換,同做三次
for (int i1 = 0; i1< (h / big); i1++) {
for (int j1 = 0; j1< (w / big); j1++) {
idct(bDCT(Rect(i1 * big, j1 * big, big, big)), iDctb(Rect(i1 * big, j1 * big, big, big)));
}
}
for (int i1 = 0; i1< (h / big); i1++) {
for (int j1 = 0; j1< (w / big); j1++) {
idct(gDCT(Rect(i1 * big, j1 * big, big, big)), iDctg(Rect(i1 * big, j1 * big, big, big)));
}
}
for (int i1 = 0; i1< (h / big); i1++) {
for (int j1 = 0; j1< (w / big); j1++) {
idct(rDCT(Rect(i1 * big, j1 * big, big, big)), iDctr(Rect(i1 * big, j1 * big, big, big)));
}
}
mv[0] = iDctb;
mv[1] = iDctg;
mv[2] = iDctr;
Mat dst;
merge(mv, dst);//通道合并
imshow("DstImage",dst);//顯示圖像
waitKey(0);
return 0;
}
效果如下:原圖:
壓縮后:
如果感覺不明顯,可以減少mask矩陣1的個數(shù)。
灰度圖int main()
{
Mat src = imread("D:\\Matlab\\toolbox\\images\\imdata\\coins.png",0);
imshow("clock", src);
src = Mat_(src);
int w = src.rows;
int h = src.cols;
int big;
big = 8;
src.convertTo(src, CV_32F, 1.0 / 255);
Mat srcDCT = Mat_(src);
for (int i1 = 0; i1< (h / big); i1++) {
for (int j1 = 0; j1< (w / big); j1++) {
dct(src(Rect(i1 * big, j1 * big, big, big)),srcDCT(Rect(i1 * big, j1 * big, big, big)));
}
}
int mask[8][8] = {
{1, 1, 1, 1, 0, 0, 0, 0},
{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},
};
double s;
for (int i1 = 0; i1< (srcDCT.rows / big); i1++) {
for (int j1 = 0; j1< (srcDCT.cols / big); j1++) {
for (int i = 0; i< big; i++)
{
for (int j = 0; j< big; j++)
{
if (mask[i % big][j % big] == 0) {
srcDCT.at(i1 * big + i, j1 * big + j) = 0;;
}
else {
s = 0;
}
}
}
}
}
Mat iDct1 = srcDCT;
for (int i1 = 0; i1< (h / big); i1++) {
for (int j1 = 0; j1< (w / big); j1++) {
idct(srcDCT(Rect(i1 * big, j1 * big, big, big)), iDct1(Rect(i1 * big, j1 * big, big, big)));
}
}
imshow("c", srcDCT);
imshow("DstImage",iDct1);
waitKey(0);
return 0;
}
感謝觀看,如有誤,請不吝賜教。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧