DCT轉換觀察低中高頻區域處理
1.write your name on the Mandrill(Baboon) image for color and grayscale images.
2.2. Split the grayscale Baboon image into 2^n (n= 0, 2, 4, 6 or 8) blocks equally.
Please make n as an input so the program can dynamically split the image. If n= 6, the block size is 64X64 each. Use DCT to convert each 64x64 block to convert the block into the frequency domain. Show the image (you may need to scale the image so the details can be displayed).
Please make n as an input so the program can dynamically split the image. If n= 6, the block size is 64X64 each. Use DCT to convert each 64x64 block to convert the block into the frequency domain. Show the image (you may need to scale the image so the details can be displayed).
當n=2->num_blocks = 2^2 = 4,代表影像被分為4塊,每塊尺寸是256*256像素
->寬度來看分2格就是2*256
->寬度來看分2格就是2*256
當n=4->num_blocks = 2^4 = 16,代表影像被分為16塊,每塊尺寸是128*128像素
->寬度來看分4格就是4*128
->寬度來看分4格就是4*128
當n=6->num_blocks = 2^6 = 64,代表影像被分為64塊,每塊尺寸是64*64像素
->寬度來看分8格就是8*64
->寬度來看分8格就是8*64
第一階段matlab code
可直接將函數跟script的.m檔案寫在一起
之後要呼叫時候 函數定義必須要在呼叫之後
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | img_color = imread("4.2.03.tiff"); % 定義文字及其屬性 text = '周冠羽'; position = [512-150 512-60]; % 定位於右下角 fontSize = 40; % 字體大小 textColor = uint8([255 255 255]); % 白色 boxColor = uint8([0 0 0]); % 背景框顏色,這裡設置為黑色 boxOpacity = 0; % 背景框不透明度,設置為0表示無背景框 fontName = 'SimSun'; % 指定一個支持中文的字體 % 添加文字到圖像 img_with_text = insertText(img_color, position, text, 'FontSize', fontSize, 'TextColor', textColor, 'BoxColor', boxColor, 'BoxOpacity', boxOpacity,'Font', fontName); figure; % 添加這行來創建一個新的圖形窗口 imshow(img_with_text); n=2; split_and_dct(img_with_text, n); function split_and_dct(img_color, n) % 讀取原始彩色圖像 %img_color = imread(image_path); if size(img_color, 3) == 4 img_color = img_color(:,:,1:3);%只保留前三個通道 end % 轉換為灰階圖像 img = rgb2gray(img_color); % 獲得圖像大小 [rows, cols] = size(img); % 計算分塊數量 %當n=2->num_blocks = 2^2 = 4,代表影像被分為4塊,每塊尺寸是256*256像素->寬度來看分2格就是2*256 %當n=4->num_blocks = 2^4 = 16,代表影像被分為16塊,每塊尺寸是128*128像素->寬度來看分4格就是4*128 %當n=6->num_blocks = 2^6 = 64,代表影像被分為64塊,每塊尺寸是64*64像素->寬度來看分8格就是8*64 num_blocks = 2^n; block_size = rows / sqrt(num_blocks); % 確保分塊大小是整數 block_size = floor(block_size); % 預分配一個矩陣來存儲 DCT 轉換後的塊 dct_blocks = zeros(rows, cols); % 分割圖像並對每個塊應用 DCT for i = 1:block_size:rows-block_size+1 for j = 1:block_size:cols-block_size+1 block = img(i:i+block_size-1, j:j+block_size-1); %提取出單一個block dct_block = dct2(block); dct_blocks(i:i+block_size-1, j:j+block_size-1) = dct_block; %將dct過後的結果儲存回原先相應位置 end end % 顯示 DCT 轉換後的圖像 figure; % 添加這行來創建一個新的圖形窗口 imagesc(log(abs(dct_blocks) + 1)); % 加 1 避免 log(0) 的情況 colormap(gray); % 使用灰度色彩映射 end |
在Matlab中
B=dct2(A) 就代表去計算A的DCT轉換存至B,此時A跟B的大小會一致。
B=dct2(A,m,n) 這也代表計算A的DCT轉存至B,只是此時A可能需要透過補0或剪裁來使B大小要是mxn。
去運行離散餘弦變換(DCT)來處理一幅圖像。
blockproc的功能其實就是將輸入進來的矩陣資料切分成固定大小矩陣分多個拆分
再去針對每一個block做運算(在此就是每一個block去運行dct2)最終合併輸出結果。
通過消除一些 DCT 係數,可以減少儲存或傳輸所需的資料量。
第一階段matlab code (改透過blockproc 函數 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | clear all img_color = imread("4.2.03.tiff"); % 定義文字及其屬性 text = '周冠羽'; position = [512-150 512-60]; % 定位於右下角 fontSize = 40; % 字體大小 textColor = uint8([255 255 255]); % 白色 boxColor = uint8([0 0 0]); % 背景框顏色,這裡設置為黑色 boxOpacity = 0; % 背景框不透明度,設置為0表示無背景框 fontName = 'SimSun'; % 指定一個支持中文的字體 % 添加文字到圖像 img_with_text = insertText(img_color, position, text, 'FontSize', fontSize, 'TextColor', textColor, 'BoxColor', boxColor, 'BoxOpacity', boxOpacity,'Font', fontName); figure; % 添加這行來創建一個新的圖形窗口 imshow(img_with_text); n=6; split_and_dct(img_with_text, n); function split_and_dct(img_color, n) % 讀取原始彩色圖像 if size(img_color, 3) == 4 img_color = img_color(:,:,1:3);%只保留前三個通道 end % 轉換為灰階圖像 img = rgb2gray(img_color); % 獲得圖像大小 [rows, cols] = size(img); % 計算分塊數量 %當n=2->num_blocks = 2^2 = 4,代表影像被分為4塊,每塊尺寸是256*256像素->寬度來看分2格就是2*256 %當n=4->num_blocks = 2^4 = 16,代表影像被分為16塊,每塊尺寸是128*128像素->寬度來看分4格就是4*128 %當n=6->num_blocks = 2^6 = 64,代表影像被分為64塊,每塊尺寸是64*64像素->寬度來看分8格就是8*64 num_blocks = 2^n; block_size = rows / sqrt(num_blocks); % 確保分塊大小是整數 block_size = floor(block_size); % 使用 blockproc 應用 DCT 變換 fun = @(block_struct) dct2(block_struct.data); Image_DCT = blockproc(img, [block_size block_size], fun); % 對 DCT 變換後的低值進行閾值處理 Image_DCT(abs(Image_DCT) < 10) = 0; % 顯示 DCT 轉換後的圖像 figure; imshow(Image_DCT); end |
這邊如果用imshow(Image_DCT) 呈現會出現非黑即白的感覺跟之前用imagesc效果有差
因為imshow 通常預期圖像數據範圍在 0 到 1(對於類型 double)或 0 到 255(對於類型 uint8),而 imagesc 會自動縮放數據到當前色彩映射的範圍。
所以底下的色彩映射會決定數值如何映射到顏色。
不同的色彩映射會產生不同的視覺效果。
閾值處理部分
所以若將顯示 DCT 轉換後的圖像
程式更改透過 imagesc 搭配 colormap就會有一樣結果呈現。
改藉由具備灰階漸層(而非黑即白)才更能幫助我們區分高頻低頻差異。
這邊就又跟上課得知的知識一樣
低頻的定義即黑白顏色交換頻率較低,而反之則稱為高頻影像區塊(相鄰像素的變化量也較大)。
3.Please draw the frequency coefficient distribution and estimate it.
要求繪製頻率係數的分佈圖,並對其進行估計。在信號處理或圖像處理中,頻率係數分佈通常是指將信號(在這裡是圖像)轉換到頻域後,不同頻率成分的大小分佈。
比方將圖像轉換到頻域(例如使用離散餘弦變換(DCT)),然後分析這些頻率成分來實現。
DCT 係數的直方圖
當您對 DCT 係數使用 histogram 函數時,MATLAB 會自動計算出包含所有數據點的範圍。
如果您的數據中有一些非常大或非常小的極端值,這將導致橫軸範圍看起來非常大。
可以通過設置 xlim 函數來實現限制橫軸的範圍,僅顯示大多數數據所在的範圍。
借此可觀察能量十分集中於低頻係數(靠近直方圖中心的值)。
第二階段matlab code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | clear all img_color = imread("4.2.03.tiff"); % 定義文字及其屬性 text = '周冠羽'; position = [512-150 512-60]; % 定位於右下角 fontSize = 40; % 字體大小 textColor = uint8([255 255 255]); % 白色 boxColor = uint8([0 0 0]); % 背景框顏色,這裡設置為黑色 boxOpacity = 0; % 背景框不透明度,設置為0表示無背景框 fontName = 'SimSun'; % 指定一個支持中文的字體 % 添加文字到圖像 img_with_text = insertText(img_color, position, text, 'FontSize', fontSize, 'TextColor', textColor, 'BoxColor', boxColor, 'BoxOpacity', boxOpacity,'Font', fontName); figure; % 添加這行來創建一個新的圖形窗口 imshow(img_with_text); n=6; split_and_dct(img_with_text, n); function split_and_dct(img_color, n) % 讀取原始彩色圖像 if size(img_color, 3) == 4 img_color = img_color(:,:,1:3);%只保留前三個通道 end % 轉換為灰階圖像 img = rgb2gray(img_color); % 獲得圖像大小 [rows, cols] = size(img); % 計算分塊數量 %當n=2->num_blocks = 2^2 = 4,代表影像被分為4塊,每塊尺寸是256*256像素->寬度來看分2格就是2*256 %當n=4->num_blocks = 2^4 = 16,代表影像被分為16塊,每塊尺寸是128*128像素->寬度來看分4格就是4*128 %當n=6->num_blocks = 2^6 = 64,代表影像被分為64塊,每塊尺寸是64*64像素->寬度來看分8格就是8*64 num_blocks = 2^n; block_size = rows / sqrt(num_blocks); % 確保分塊大小是整數 block_size = floor(block_size); % 使用 blockproc 應用 DCT 變換 fun = @(block_struct) dct2(block_struct.data); Image_DCT = blockproc(img, [block_size block_size], fun); % 呼叫函數來顯示 DCT 係數分布 display_dct_histogram(Image_DCT); % 對 DCT 變換後的低值進行閾值處理 %Image_DCT(abs(Image_DCT) < 10) = 0; % 顯示 DCT 轉換後的圖像 figure; imagesc(log(abs(Image_DCT) + 1)); colormap(gray); colorbar; %顯示顏色欄 end function display_dct_histogram(Image_DCT) % 新建一個圖形視窗來顯示 DCT 係數的值方圖 figure; % 展平 DCT 係數矩陣為一維數組 dct_values = Image_DCT(:); % 計算 DCT 係數的值方圖 histogram(dct_values, 'BinWidth', 1); % 您可以根據需要調整 BinWidth 的值 % 給值方圖添加標題和軸標籤 title('Histogram of DCT Coefficients'); xlabel('DCT Coefficient Value'); ylabel('Frequency'); % 限制 X 軸的範圍以排除零係數的影響(如果需要的話) %xlim([min(dct_values(dct_values ~= 0)), max(dct_values)]); xlim([-256 256]); % 根據您的數據調整這些值 end |
4.Start to reserve 8x8, 9x9, ……, mxm block on the top left corner of each DCT domain block and see at what value of m you can start to see the clear picture of Baboon image with your name. Please calculate the PSNR and MSE of image and show your works. (You may want to tabulate the results.)
第三階段matlab code
嘗試去觀察每一個DCT block 保留最左上角8*8,9*9.....12*12..16*16到哪階段的重建效果最好
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | clear all close all force img_color = imread("4.2.03.tiff"); % 定義文字及其屬性 text = '周冠羽'; position = [512-150 512-60]; % 定位於右下角 fontSize = 40; % 字體大小 textColor = uint8([255 255 255]); % 白色 boxColor = uint8([0 0 0]); % 背景框顏色,這裡設置為黑色 boxOpacity = 0; % 背景框不透明度,設置為0表示無背景框 fontName = 'SimSun'; % 指定一個支持中文的字體 % 添加文字到圖像 img_with_text = insertText(img_color, position, text, 'FontSize', fontSize, 'TextColor', textColor, 'BoxColor', boxColor, 'BoxOpacity', boxOpacity,'Font', fontName); figure; % 添加這行來創建一個新的圖形窗口 imshow(img_with_text); n=6; split_and_dct(img_with_text, n); function split_and_dct(img_color, n) % 讀取原始彩色圖像 if size(img_color, 3) == 4 img_color = img_color(:,:,1:3);%只保留前三個通道 end % 轉換為灰階圖像 img_gray = rgb2gray(img_color); % 獲得圖像大小 [rows, cols] = size(img_gray); % 計算分塊數量 %當n=2->num_blocks = 2^2 = 4,代表影像被分為4塊,每塊尺寸是256*256像素->寬度來看分2格就是2*256 %當n=4->num_blocks = 2^4 = 16,代表影像被分為16塊,每塊尺寸是128*128像素->寬度來看分4格就是4*128 %當n=6->num_blocks = 2^6 = 64,代表影像被分為64塊,每塊尺寸是64*64像素->寬度來看分8格就是8*64 num_blocks = 2^n; block_size = rows / sqrt(num_blocks); % 確保分塊大小是整數 block_size = floor(block_size); % 使用 blockproc 應用 DCT 變換 fun = @(block_struct) dct2(block_struct.data); Image_DCT = blockproc(img_gray, [block_size block_size], fun); % 呼叫函數來顯示 DCT 係數分布 display_dct_histogram(Image_DCT); % 顯示 DCT 轉換後的圖像 figure; imagesc(log(abs(Image_DCT) + 1)); colormap(gray); colorbar; %顯示顏色欄 m_lowerbound = 12 m_upperbound = 16 % 設置 m 的範圍,例如從 8 到 12 或12 到 16 for m = m_lowerbound:m_upperbound % 應用 IDCT,但僅保留每個塊的 mxm 區域 fun_idct = @(block_struct) idct2(reserve_dct(block_struct.data, m)); img_reconstructed = blockproc(Image_DCT, [block_size block_size], fun_idct); % 顯示重建的整體圖像 figure; imshow(img_reconstructed, []); title(['Reconstructed Image with m = ' num2str(m)]); % 整個圖像的質量評估-計算 PSNR 或 MSE psnr_val = calculate_psnr(img_gray, img_reconstructed); mse_val = calculate_mse(img_gray, img_reconstructed); % 顯示 PSNR 和 MSE disp(['PSNR for m = ' num2str(m) ': ' num2str(psnr_val)]); disp(['MSE for m = ' num2str(m) ': ' num2str(mse_val)]); end end %計算 MSE 的函數 function mse_value = calculate_mse(original, reconstructed) % 確保兩個圖像具有相同的數據類型 %將重建圖像轉換為 uint8 類型,這樣就可以與原始圖像進行比較了 reconstructed_uint8 = im2uint8(reconstructed); % 計算 MSE mse_value = immse(original, reconstructed_uint8); end %計算 PSNR 的函數 function psnr_value = calculate_psnr(original, reconstructed) % 確保兩個圖像具有相同的數據類型 %將重建圖像轉換為 uint8 類型,這樣就可以與原始圖像進行比較了 reconstructed_uint8 = im2uint8(reconstructed); % 計算 MSE mse = immse(original, reconstructed_uint8); % 計算 PSNR psnr_value = 10 * log10(255^2 / mse); end function block = reserve_dct(block, m) % 保留左上角的 mxm DCT 係數,其餘部分設為零 block(m+1:end, :) = 0; block(:, m+1:end) = 0; end function display_dct_histogram(Image_DCT) % 新建一個圖形視窗來顯示 DCT 係數的值方圖 figure; % 展平 DCT 係數矩陣為一維數組 dct_values = Image_DCT(:); % 計算 DCT 係數的值方圖 histogram(dct_values, 'BinWidth', 1); % 您可以根據需要調整 BinWidth 的值 % 給值方圖添加標題和軸標籤 title('Histogram of DCT Coefficients'); xlabel('DCT Coefficient Value'); ylabel('Frequency'); % 限制 X 軸的範圍以排除零係數的影響(如果需要的話) %xlim([min(dct_values(dct_values ~= 0)), max(dct_values)]); xlim([-256 256]); % 根據您的數據調整這些值 end |
均方誤差(mean square error, MSE)
影像品質的均方誤差評估方法是一種常用的影像品質評估方法,是指被評估影像與參考影像對應位置像素值誤差的平方平均值誤差。假設有一幅參考圖像f(x,y),另有一個受到污染的圖像g(x,y),如欲對圖像g(x,y)進行質量評價,其均方誤差計算公式為:
根據均方誤差的定義,誤差值越大,表示影像像素值整體差異大,影像品質越差;反之,均方誤差越小,表示影像品質越好。均方誤差為0,則被評估影像與參考影像完全一致。
訊號雜訊比(SNR)與峰值訊號雜訊比(PSNR)
影像的訊號雜訊比也是常用的影像品質評估指標之一,是參考影像像素值的平方平均值與均方誤差比值的對數的10倍。若一幅參考影像以f(x,y)表示,而受污染的影像以g(x,y)表示,如欲對影像g(x,y)進行品質評價。
訊號雜訊比(signal noise ration , SNR)誤差計算公式為:
為了消除影像自身像素值大小對評估指標的影響。
通常會藉由峰值信噪比(peak signal noise ration, PSNR),這是與訊號雜訊比相似的品質度量準則。 PSNR定義為影像所容許的最大像素值平方與均方誤差比值的對數的10倍。如以8位元灰階影像為例,由於最大像素值為255,因此峰值訊號雜訊比公式為
MSE 值越低,表示圖像重建的質量越好,反之MSE越高則越差。
剛好跟PSNR有點成反比
PSNR 越高,表示圖像質量越好。
PSNR 值非常低,這通常表示圖像質量較差,可能由於重建圖像與原始圖像之間有顯著的差異。
程式說明:
reserve_dct(block, m)這個函數,會直接透過矩陣索引將行數超過 m 的所有行元素設為零,然後將列數超過 m 的所有列元素設為零,藉此來實踐保留 block 中左上角的 m x m 區域的 DCT 係數,並將其餘部分設為零。
fun_idct = @(block_struct) idct2(reserve_dct(block_struct.data, m));
img_reconstructed = blockproc(Image_DCT, [block_size block_size], fun_idct);
匿名函數 fun_idct,其中 block_struct 是這個匿名函數的輸入參數。
這邊就想成可以把一個方法先不具名的定義然後可以類似變數去儲存一個function處理過程的概念。(也就是說fun_idct這個變數名稱後面assign一段處理方法會做逆DCT )
idct2(reserve_dct(block_struct.data, m)) 則是這個匿名函數的主體
首先對 block_struct.data(即一塊 DCT 轉換後的數據)調用 reserve_dct 函數,然後對修改後的數據(僅保留左上角的 m x m DCT 係數,其餘設為零)進行逆 DCT 轉換(idct2)。
函數 blockproc
接受三個參數:
要處理的圖像(這裡是 Image_DCT)
每個塊的尺寸([block_size block_size]),也就是固定幾乘幾滑動變更套用固定range的部分。
應用於每個塊的函數(這裡是我們剛剛定義的 fun_idct)。
實驗觀察過程:
對於 m = 12 到 15,PSNR 和 MSE 的值幾乎相同,代表可能在這些 m 值下的 DCT 壓縮對圖像質量的影響是類似的。
但是在 m = 16 時,PSNR 和 MSE 都有輕微的變化,這可能表示在這個 m 值下的圖像重建質量稍微好一點。
這裡調整一下區間改為26~30就可觀察右下角壓上去的名字有開始變明顯一點。
要一次關掉所有視窗就靠以下指令
close all force
close all force
5.In each DCT block, keep the highest 100, 200, 300, … l coefficients (absolute value) and set the rest pixels at value 0, see at what value you can clearly see the Baboon image with your name. Please calculate the PSNR and MSE of image and show your works.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | clear all close all force img_color = imread("4.2.03.tiff"); % 定義文字及其屬性 text = '周冠羽'; position = [512-150 512-60]; % 定位於右下角 fontSize = 40; % 字體大小 textColor = uint8([255 255 255]); % 白色 boxColor = uint8([0 0 0]); % 背景框顏色,這裡設置為黑色 boxOpacity = 0; % 背景框不透明度,設置為0表示無背景框 fontName = 'SimSun'; % 指定一個支持中文的字體 % 添加文字到圖像 img_with_text = insertText(img_color, position, text, 'FontSize', fontSize, 'TextColor', textColor, 'BoxColor', boxColor, 'BoxOpacity', boxOpacity,'Font', fontName); figure; % 添加這行來創建一個新的圖形窗口 imshow(img_with_text); n=6; split_and_dct(img_with_text, n); function split_and_dct(img_color, n) % 讀取原始彩色圖像 if size(img_color, 3) == 4 img_color = img_color(:,:,1:3);%只保留前三個通道 end % 轉換為灰階圖像 img_gray = rgb2gray(img_color); % 獲得圖像大小 [rows, cols] = size(img_gray); % 計算分塊數量 %當n=2->num_blocks = 2^2 = 4,代表影像被分為4塊,每塊尺寸是256*256像素->寬度來看分2格就是2*256 %當n=4->num_blocks = 2^4 = 16,代表影像被分為16塊,每塊尺寸是128*128像素->寬度來看分4格就是4*128 %當n=6->num_blocks = 2^6 = 64,代表影像被分為64塊,每塊尺寸是64*64像素->寬度來看分8格就是8*64 num_blocks = 2^n; block_size = rows / sqrt(num_blocks); % 確保分塊大小是整數 block_size = floor(block_size); % 使用 blockproc 應用 DCT 變換 fun = @(block_struct) dct2(block_struct.data); Image_DCT = blockproc(img_gray, [block_size block_size], fun); % 呼叫函數來顯示 DCT 係數分布 display_dct_histogram(Image_DCT); % 顯示 DCT 轉換後的圖像 figure; imagesc(log(abs(Image_DCT) + 1)); colormap(gray); colorbar; %顯示顏色欄 %DCT轉換後取最大的N個值其餘歸零 topN=100; Image_DCT_TopN = blockproc(img_gray, [block_size block_size], @(block) reserve_top_dct_coeffs(block.data,block_size ,topN)); % 顯示 DCT 轉換後的圖像 figure; imagesc(log(abs(Image_DCT_TopN) + 1)); colormap(gray); colorbar; %顯示顏色欄 %m_lowerbound = 12 %m_upperbound = 16 m_lowerbound = 26 m_upperbound = 30 % 設置 m 的範圍,例如從 8 到 12 或12 到 16 for m = m_lowerbound:m_upperbound % 應用 IDCT,但僅保留每個塊的 mxm 區域 fun_idct = @(block_struct) idct2(reserve_dct(block_struct.data, m)); %DCT轉換後取最大的N個值其餘歸零 %fun_idct = @(block_struct) idct2(reserve_top_dct_coeffs(block_struct.data, 100 )); img_reconstructed = blockproc(Image_DCT, [block_size block_size], fun_idct); % 顯示重建的整體圖像 figure; imshow(img_reconstructed, []); title(['Reconstructed Image with m = ' num2str(m)]); % 整個圖像的質量評估-計算 PSNR 或 MSE psnr_val = calculate_psnr(img_gray, img_reconstructed); mse_val = calculate_mse(img_gray, img_reconstructed); % 顯示 PSNR 和 MSE disp(['PSNR for m = ' num2str(m) ': ' num2str(psnr_val)]); disp(['MSE for m = ' num2str(m) ': ' num2str(mse_val)]); end end %計算 MSE 的函數 function mse_value = calculate_mse(original, reconstructed) % 確保兩個圖像具有相同的數據類型 %將重建圖像轉換為 uint8 類型,這樣就可以與原始圖像進行比較了 reconstructed_uint8 = im2uint8(reconstructed); % 計算 MSE mse_value = immse(original, reconstructed_uint8); end %計算 PSNR 的函數 function psnr_value = calculate_psnr(original, reconstructed) % 確保兩個圖像具有相同的數據類型 %將重建圖像轉換為 uint8 類型,這樣就可以與原始圖像進行比較了 reconstructed_uint8 = im2uint8(reconstructed); % 計算 MSE mse = immse(original, reconstructed_uint8); % 計算 PSNR psnr_value = 10 * log10(255^2 / mse); end function block = reserve_dct(block, m) % 保留左上角的 mxm DCT 係數,其餘部分設為零 block(m+1:end, :) = 0; block(:, m+1:end) = 0; end function dct_topMax_coeffs = reserve_top_dct_coeffs(data,block_size, topN) data_dct_out = dct2(data); TopN_value = abs(reshape(data_dct_out,[1,block_size*block_size])); TopN_value = min(maxk(TopN_value,topN)); data_dct_out(abs(data_dct_out) < TopN_value) = 0; dct_topMax_coeffs = idct2(data_dct_out); dct_topMax_coeffs = rescale(dct_topMax_coeffs); end function display_dct_histogram(Image_DCT) % 新建一個圖形視窗來顯示 DCT 係數的值方圖 figure; % 展平 DCT 係數矩陣為一維數組 dct_values = Image_DCT(:); % 計算 DCT 係數的值方圖 histogram(dct_values, 'BinWidth', 1); % 您可以根據需要調整 BinWidth 的值 % 給值方圖添加標題和軸標籤 title('Histogram of DCT Coefficients'); xlabel('DCT Coefficient Value'); ylabel('Frequency'); % 限制 X 軸的範圍以排除零係數的影響(如果需要的話) %xlim([min(dct_values(dct_values ~= 0)), max(dct_values)]); xlim([-256 256]); % 根據您的數據調整這些值 end |
6.Use the Matlab codes for JPEG, please add the chrominance quantization table from classnotes 4.2. to compress Baboon color image.
Please plot
(1) the PSNR vs. quality factor from 1-100
(2) the image size vs. quality factor from 1-100
第五階段matlab code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | clear all close all force img_color = imread("4.2.03.tiff"); % 定義文字及其屬性 text = '周冠羽'; position = [512-150 512-60]; % 定位於右下角 fontSize = 40; % 字體大小 textColor = uint8([255 255 255]); % 白色 boxColor = uint8([0 0 0]); % 背景框顏色,這裡設置為黑色 boxOpacity = 0; % 背景框不透明度,設置為0表示無背景框 fontName = 'SimSun'; % 指定一個支持中文的字體 % 添加文字到圖像 img_with_text = insertText(img_color, position, text, 'FontSize', fontSize, 'TextColor', textColor, 'BoxColor', boxColor, 'BoxOpacity', boxOpacity,'Font', fontName); figure; % 添加這行來創建一個新的圖形窗口 imshow(img_with_text); %n=6; %split_and_dct(img_with_text, n); %JPEG 壓縮過程 chrominanceQuantTable = [17 18 24 47 99 99 99 99; 18 21 26 66 99 99 99 99; 24 26 56 99 99 99 99 99; 47 66 99 99 99 99 99 99; 99 99 99 99 99 99 99 99; 99 99 99 99 99 99 99 99; 99 99 99 99 99 99 99 99; 99 99 99 99 99 99 99 99]; quality_factors = 1:100; % 定義質量因子範圍 psnr_values = zeros(1, 100); % 初始化 PSNR 值陣列 compressed_sizes = zeros(1, 100); % 初始化壓縮後大小陣列 % 計算 PSNR 和壓縮後圖像大小的循環 for qf = quality_factors % 進行 JPEG 壓縮 compressed_img = jpeg_compress(img_with_text, chrominanceQuantTable, qf); % 進行 JPEG 解壓縮 decompressed_img = jpeg_decompress(compressed_img, chrominanceQuantTable, qf); % 計算 PSNR psnr_values(qf) = calculate_psnr(img_with_text, decompressed_img); % 計算壓縮後的圖像大小 compressed_sizes(qf) = numel(find(compressed_img ~= 0)); end % 繪製 PSNR 與質量因子的關係圖 figure; plot(quality_factors, psnr_values); title('PSNR vs Quality Factor'); xlabel('Quality Factor'); ylabel('PSNR (dB)'); % 繪製壓縮後的圖像大小與質量因子的關係圖 figure; plot(quality_factors, compressed_sizes); title('Compressed Image Size vs Quality Factor'); xlabel('Quality Factor'); ylabel('Image Size (bytes)'); function compressed_img = jpeg_compress(img, chrominanceQuantTable, qf) % 將圖像轉換為 YCbCr img_ycbcr = rgb2ycbcr(img); [rows, cols, ~] = size(img_ycbcr); compressed_img = zeros(rows, cols, 'single'); for i = 1:8:rows for j = 1:8:cols for channel = 1:3 % 對每個 8x8 塊進行 DCT 變換 block = double(img_ycbcr(i:i+7, j:j+7, channel)) - 128; dct_block = dct2(block); % 進行量化 quantized_block = round(dct_block ./ (chrominanceQuantTable * qf)); % 儲存量化後的塊 compressed_img(i:i+7, j:j+7, channel) = quantized_block; end end end end function decompressed_img = jpeg_decompress(compressed_img, chrominanceQuantTable, qf) [rows, cols, ~] = size(compressed_img); decompressed_img_ycbcr = zeros(rows, cols, 3, 'uint8'); for i = 1:8:rows for j = 1:8:cols for channel = 1:3 % 取出量化後的塊 quantized_block = compressed_img(i:i+7, j:j+7, channel); % 進行反量化 dequantized_block = quantized_block .* (chrominanceQuantTable * qf); % 進行 IDCT 變換 idct_block = idct2(dequantized_block) + 128; % 儲存解壓縮後的塊 decompressed_img_ycbcr(i:i+7, j:j+7, channel) = uint8(idct_block); end end end % 將圖像從 YCbCr 轉換回 RGB decompressed_img = ycbcr2rgb(decompressed_img_ycbcr); end function split_and_dct(img_color, n) % 讀取原始彩色圖像 if size(img_color, 3) == 4 img_color = img_color(:,:,1:3);%只保留前三個通道 end % 轉換為灰階圖像 img_gray = rgb2gray(img_color); % 獲得圖像大小 [rows, cols] = size(img_gray); % 計算分塊數量 %當n=2->num_blocks = 2^2 = 4,代表影像被分為4塊,每塊尺寸是256*256像素->寬度來看分2格就是2*256 %當n=4->num_blocks = 2^4 = 16,代表影像被分為16塊,每塊尺寸是128*128像素->寬度來看分4格就是4*128 %當n=6->num_blocks = 2^6 = 64,代表影像被分為64塊,每塊尺寸是64*64像素->寬度來看分8格就是8*64 num_blocks = 2^n; block_size = rows / sqrt(num_blocks); % 確保分塊大小是整數 block_size = floor(block_size); % 使用 blockproc 應用 DCT 變換 fun = @(block_struct) dct2(block_struct.data); Image_DCT = blockproc(img_gray, [block_size block_size], fun); % 呼叫函數來顯示 DCT 係數分布 display_dct_histogram(Image_DCT); % 顯示 DCT 轉換後的圖像 figure; imagesc(log(abs(Image_DCT) + 1)); colormap(gray); colorbar; %顯示顏色欄 %DCT轉換後取最大的N個值其餘歸零 topN=100; Image_DCT_TopN = blockproc(img_gray, [block_size block_size], @(block) reserve_top_dct_coeffs(block.data,block_size ,topN)); % 顯示 DCT 轉換後的圖像 figure; imagesc(log(abs(Image_DCT_TopN) + 1)); colormap(gray); colorbar; %顯示顏色欄 %m_lowerbound = 12 %m_upperbound = 16 m_lowerbound = 26 m_upperbound = 30 % 設置 m 的範圍,例如從 8 到 12 或12 到 16 for m = m_lowerbound:m_upperbound % 應用 IDCT,但僅保留每個塊的 mxm 區域 fun_idct = @(block_struct) idct2(reserve_dct(block_struct.data, m)); %DCT轉換後取最大的N個值其餘歸零 %fun_idct = @(block_struct) idct2(reserve_top_dct_coeffs(block_struct.data, 100 )); img_reconstructed = blockproc(Image_DCT, [block_size block_size], fun_idct); % 顯示重建的整體圖像 figure; imshow(img_reconstructed, []); title(['Reconstructed Image with m = ' num2str(m)]); % 整個圖像的質量評估-計算 PSNR 或 MSE psnr_val = calculate_psnr(img_gray, img_reconstructed); mse_val = calculate_mse(img_gray, img_reconstructed); % 顯示 PSNR 和 MSE disp(['PSNR for m = ' num2str(m) ': ' num2str(psnr_val)]); disp(['MSE for m = ' num2str(m) ': ' num2str(mse_val)]); end end %計算 MSE 的函數 function mse_value = calculate_mse(original, reconstructed) % 確保兩個圖像具有相同的數據類型 %將重建圖像轉換為 uint8 類型,這樣就可以與原始圖像進行比較了 reconstructed_uint8 = im2uint8(reconstructed); % 計算 MSE mse_value = immse(original, reconstructed_uint8); end %計算 PSNR 的函數 function psnr_value = calculate_psnr(original, reconstructed) % 確保兩個圖像具有相同的數據類型 %將重建圖像轉換為 uint8 類型,這樣就可以與原始圖像進行比較了 reconstructed_uint8 = im2uint8(reconstructed); % 計算 MSE mse = immse(original, reconstructed_uint8); % 計算 PSNR psnr_value = 10 * log10(255^2 / mse); end function block = reserve_dct(block, m) % 保留左上角的 mxm DCT 係數,其餘部分設為零 block(m+1:end, :) = 0; block(:, m+1:end) = 0; end function dct_topMax_coeffs = reserve_top_dct_coeffs(data,block_size, topN) data_dct_out = dct2(data); TopN_value = abs(reshape(data_dct_out,[1,block_size*block_size])); TopN_value = min(maxk(TopN_value,topN)); data_dct_out(abs(data_dct_out) < TopN_value) = 0; dct_topMax_coeffs = idct2(data_dct_out); dct_topMax_coeffs = rescale(dct_topMax_coeffs); end function display_dct_histogram(Image_DCT) % 新建一個圖形視窗來顯示 DCT 係數的值方圖 figure; % 展平 DCT 係數矩陣為一維數組 dct_values = Image_DCT(:); % 計算 DCT 係數的值方圖 histogram(dct_values, 'BinWidth', 1); % 您可以根據需要調整 BinWidth 的值 % 給值方圖添加標題和軸標籤 title('Histogram of DCT Coefficients'); xlabel('DCT Coefficient Value'); ylabel('Frequency'); % 限制 X 軸的範圍以排除零係數的影響(如果需要的話) %xlim([min(dct_values(dct_values ~= 0)), max(dct_values)]); xlim([-256 256]); % 根據您的數據調整這些值 end |
留言
張貼留言