Powered by and 圖示來源

2011年12月25日 星期日

這學期的數位視訊系統老師叫我們寫一個作業,題目:
是說把一張彩色的圖以RBG為做向量(vector),再透過generalized Lloyd algorithm去把圖片重新編碼。

大學時都沒這麼認真用過MATLAB! @@

glloyd_training.m
function [codebook, Index] = glloyd_training(ImgPxl, CS, Vector_Len, er, x, y)
  Training_idx = (x*y*3)/Vector_Len ;
  Training_set = reshape(ImgPxl(:), Training_idx, Vector_Len);
  codebook = zeros(CS, Vector_Len) ;

  Child_group = fix(Training_idx/CS); %每個codebook 值將會代表幾個原始值,取整數
  for i = 1 : CS %先分成codesize 區塊,每一塊先取平均值
    codebook(i,:) = mean(Training_set(((i-1)*Child_group+1):i*Child_group,:) );
  end

  old_MSE = 0;
  inited=0;

  MSE_diff=100;
  min_diff =2;
  %新舊codebook 的MSE相差小於min_diff,就不再做下去. 當作是完成了.
  while (MSE_diff>min_diff)
    if (inited>0)
      for i = 1 : CS
        same_group = find(Index == i) ;
        if ~isempty(same_group)
          codebook(i, :) = mean(Training_set(same_group, :));
        else %沒有任何值落在這邊 就抓附近的來補一下
          if i == 1
            codebook(i,:) = mean(codebook([2 3],:)) ;
          elseif i == CS
            codebook(i,:) = mean(codebook([CS-1 CS-2],:)) ;
          else
            codebook(i,:) = mean(codebook([i+1 i-1],:)) ;
          end
        end
      end
    else
      inited =1;
    end

  coded_value = zeros(Training_idx,1);
  %將所有的vector 依codebook分類
  for i = 1 : Training_idx
    Current_Vector = Training_set(i,:);
    %分身為CS筆
    Current_Vector_n = Current_Vector(ones(CS,1),:);
    %算出MSE
    vector_MSE = sum(((Current_Vector_n-codebook).^2).')/Vector_Len ;
    %選MSE最小的
    [coded_value(i), Index(i)] = min(vector_MSE) ;
  end

  VQImg = codebook(Index,:) ;
  VQImg = reshape(VQImg(:), y, x, 3) ;
  MSE = mse(ImgPxl - VQImg);

  if (old_MSE)
    MSE_diff = abs(old_MSE-MSE);
  else
    MSE_diff = abs(MSE);
  end
    old_MSE= MSE;
    MSE_diff
  end
廣告



VQ.m
function VQ(CS)
%Usage: VQ(CS)
%CS is codebook size(L)
    Vector_Len = 3;
    er = 5;
    ImgFile = 'Lena.jpg';

    ImgPxl = double(imread(ImgFile)) ;
    Pic_info = imfinfo(ImgFile);

    [codebook, index] = glloyd_training(ImgPxl, CS, Vector_Len, er, Pic_info.Width, Pic_info.Height) ;

    VQImg = codebook(index,:) ;

    VQImg = reshape(VQImg(:), Pic_info.Height, Pic_info.Width, 3) ;
    MSE = mse(ImgPxl - VQImg)

    index = gcf();
    if (index ==1)
    figure(index);
        imshow(uint8(ImgPxl)) ;
        title('Source' ) ;
    end
    figure(index+1) ;
    imshow(uint8(VQImg)) ;
    title(['VQ L=',int2str(CS)] );

檔名在VQ.m是寫死的
ImgFile = 'Lena.jpg';

把程試簡化,讓助教比較好處理。
>> help VQ
Usage: VQ(CS)
CS is codebook size(L)

跑幾張圖來試試看好了!

source
廣告




VQ(8)

VQ(32)

VQ(128)

居然V32就已經看不太出來有什麼差別了.
這個故事告訴我們,"做影像處理的報告,乖乖的用Lenna就對了"

matlab code參考自:
http://www.wretch.cc/blog/Lak4CYUT/3518815


##HIDEME##

##HIDEME##