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).


當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



第一階段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。




更簡短寫法就是在將迴圈處裡的block部分改透過 blockproc 函數
去運行離散餘弦變換(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 係數的直方圖

直方圖的橫軸(X軸)顯示的範圍由數據中的最大值和最小值決定。
當您對 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



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.


第四階段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
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





留言

這個網誌中的熱門文章

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header

經得起原始碼資安弱點掃描的程式設計習慣培養(三)_7.Cross Site Scripting(XSS)_Stored XSS_Reflected XSS All Clients

(2021年度)駕訓學科筆試準備題庫歸納分析_法規是非題