天天看點

【語音隐寫】基于matlab GUI DCT音頻數字水印嵌入提取【含Matlab源碼 837期】

一、離散小波變換的音頻信号數字水印技術簡介

​0 引言​

近年來, 數字水印技術的作用越來越重要。數字水印技術是将一些辨別資訊直接嵌入數字載體當中, 或間接表示在信号載體中, 且不影響原載體的使用價值。通過隐藏在載體中的這些資訊, 可以判斷資訊是否被篡改, 具有防僞溯源、保護資訊安全、版權保護等作用。對于廣播轉播台站而言, 是廣播音頻的中轉站, 在廣播信号發送至千家萬戶之前務必保證信号的安全可靠, 但現在的大部分台站隻是利用人耳的判斷, 以及不同信源之間的比較, 具有較大的局限性。若利用數字水印的特性, 應用于廣播節目中可以有效地防止信号插播, 可靠地保護信号安全, 保障廣播的安全播出。

​1 音頻數字水印技術分類​

根據數字水印在音頻信号中的處理技術, 可将數字水印分為時域、變換域、壓縮域數字水印。

​1.1 時域數字水印​

在時域數字水印技術中, 直接将水印資訊嵌入至音頻信号中, 通常會選擇隐藏在信号不重要部位, 以保證其嵌入水印不影響原音頻信号的監聽效果。時域水印技術的實作較為容易且運算量小, 簡單直接, 但是魯棒性差, 容易被破解, 抵抗力較差。

​1.2 變換域數字水印​

在變換域數字水印中, 音頻信号需經過時域至變換域的轉換, 通常的變換域有離散餘弦變換 (DCT, Discrete Cosine Transform) 、離散傅立葉變換 (DFT, Discrete Fourier transform) 、離散小波變換 (DWT, Discrete Wavelet Transform) 等。在變換域中嵌入水印資訊, 通過反變換得到嵌入水印的音頻時域信号。變換域水印技術較時域水印技術複雜, 但變換域嵌入的水印資訊較時域而言, 不可見性更強, 隐蔽性更好, 魯棒性更好。本文的研究主要基于DWT的音頻信号的水印資訊的嵌入與提取。

​1.3 壓縮域數字水印​

在時域和變換域的水印技術, 都是直接将水印信号嵌入未壓縮的音頻格式中, 但是通常在音頻信号的傳輸或存儲中需要對音頻信号進行壓縮編碼 (例如WMA、MP3等) , 是以壓縮域數字水印也是水印技術也具有較大的實用價值。壓縮域數字水印技術大緻可分為三類: (1) 在非壓縮域嵌入水印, 将音頻信号與水印資訊一起壓縮; (2) 在壓縮域中, 直接将水印資訊嵌入壓縮的音頻信号中; (3) 将壓縮後的信号進行解壓縮, 然後嵌入水印資訊, 最後将水印資訊和解壓後的音頻信号一起壓縮。總的來說, 壓縮域水印技術的編解碼系統過于複雜, 受壓縮編碼格式限制大, 壓縮後的音頻信号已經去除了備援, 是以加入水印的難度大, 壓縮域水印技術有待進一步研究。

二、部分源代碼

function varargout = main(varargin)
% MAIN MATLAB code for main.fig
%      MAIN, by itself, creates a new MAIN or raises the existing
%      singleton*.
%
%      H = MAIN returns the handle to a new MAIN or the handle to
%      the existing singleton*.
%
%      MAIN('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in MAIN.M with the given input arguments.
%
%      MAIN('Property','Value',...) creates a new MAIN or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before main_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to main_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help main

% Last Modified by GUIDE v2.5 15-Apr-2021 12:58:02

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
    'gui_Singleton',  gui_Singleton, ...
    'gui_OpeningFcn', @main_OpeningFcn, ...
    'gui_OutputFcn',  @main_OutputFcn, ...
    'gui_LayoutFcn',  [] , ...
    'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before main is made visible.
function main_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to main (see VARARGIN)

% Choose default command line output for main
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes main wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = main_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
addpath('.\wavelet\')%添加小波變換工具箱
%% 選擇音頻
[file1,pathname]=uigetfile('*.wav','請選擇要識别的樣本');%跳出對話框
fname=fullfile(pathname,file1);%音頻檔案名
[X,fs]=audioread(fname); %讀入音頻檔案
s=get(handles.popupmenu1,'Value'); 

handles.axes1 %標明坐标軸1
subplot(2,2,1); %子視窗
plot(X);     %顯示音頻檔案波形
title('原始音頻信号');
handles.X=X;%儲存原始音頻信号
handles.fs=fs;%儲存原始音頻信号頻率
handles.s=s;
guidata(hObject, handles);
% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
%% 選擇水印
[file1,pathname]=uigetfile('*.bmp','請選擇要識别的樣本');%跳出對話框
fname=fullfile(pathname,file1);%選擇圖檔
key=35;%密鑰參數
%Arnold置換次數,作為密鑰
Orignalmark=double(imread(fname));  %讀入64*64的水印圖檔
[wrow,wcol]=size(Orignalmark);  %圖像大小wrow行,wcol列
if wrow~=wcol
    error('wrow~=wcol error');%如果行列不相等則報錯
end
%--- 測試密鑰key是否超出範圍---------
n=check_arnold(wrow);
if (key+1)>n
    error('arnold key error');
end
s=get(handles.popupmenu1,'Value'); 

subplot(2,2,2); hold on
imshow(Orignalmark),title('原始圖像');
handles.Orignalmark=Orignalmark;%儲存原始圖像
handles.n=n;
handles.s=s;
guidata(hObject, handles);
% --- Executes on button press in pushbutton3.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
%% 嵌入水印
%水印嵌入--------------------------------------------------
X=handles.X;%讀取音頻
Orignalmark=handles.Orignalmark;%讀取水印圖像
fs=handles.fs;%頻率
s=handles.s;%算法類型
[wrow,wcol]=size(Orignalmark);
key=35;%密鑰
if s==2
    
    Arnoldw=arnold(Orignalmark,wrow,key); %對水印圖像進行Arnold轉化
    [c,l]=wavedec(X,2,'db4'); % 
    ca2=appcoef(c,l,'db4',2); % 
    cd2=detcoef(c,l,2);  %  
    cd1=detcoef(c,l,1);  % 
    lca=length(ca2);  %低頻長度
    blocksize=fix(lca/(wrow*wcol)); %每塊的大小
    water_vector=reshape(Arnoldw,1,wrow*wcol);  %将置亂後的水印轉化為一維的
    wlength=wrow*wcol;  %水印的長度
    a=0.25;  %量化步長
    j=1;
    for i=1:wlength
        Block=ca2(j:j+blocksize-1);
        [U,S,V]=svd(double(Block));
        cc=floor(S(1,1)/a);
        if(Arnoldw(i)==1)           %嵌入奇數倍
            if(mod(cc,2)==0)
                cc=cc+1;
            end
            S(1,1)=a*cc;
        end
        if(Arnoldw(i)==0)            %嵌入偶數倍
            if(mod(cc,2)==1)
                cc=cc+1;
            end
            S(1,1)=a*cc;
        end
        Blockw=U*S*V';          % 還原
        ca2(j:j+blocksize-1)=Blockw;
        j=j+blocksize;
    end
    c1=[ca2',cd2',cd1']';
    MarkedX=waverec(c1,l,'db4');%b為量化嵌入水印後的音頻資料
else
    A=X;
    L = size(A);% 用變量L存儲音頻A的長度
    M=Orignalmark;
    BW = im2bw(M);% 将圖像Lena.bmp轉化為二值圖并存入變量BW
    % 計算水印矩陣大小
    [M1,M2] = size(BW);
    % M12為中間變量,避免每次都計算M1*M2
    M12 = M1*M2;
    % 降維,将水印資訊得到的一維序列存入序列C中
    C = reshape(BW,1,M12);
    n = M12;
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % 對水印信号進行擴頻處理,效果不是很好
    % 擴頻系數為2
    n = M12*2;
    M = zeros(n,1);
    % 産生密鑰序列M
    for k = 1 : n
        if mod(k,4) == 0
            M(k) = 1;
        else
            M(k) = 0;
        end
        % 水印信号序列分别按位與密鑰異或
        l = ceil(k/2);
        S(k) = bitxor(C(l),M(k));
    end
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    % 嵌入一個水印資訊需要的音頻資料為N
    N = 10;
    length1 = n*10;
    % 将原始音頻信号分解為Ae和Ar兩部分
    i = 1 : length1;
    j = [1];
    % 取矩陣A的l到length行建構矩陣Ae
    Ae = A(i,j);
    % Ae(i,j)
    i = length1+1 : L;
    % 取矩陣A的length到L行第一列建構矩陣Ar
    Ar = A(i,j);
    
    
    % 建立元胞B,每個音頻資料段Ae(m)是B的一個元素
    k = 1;
    % 建立M1 x M2行l列的元胞
    B = cell(n,1);
    th = n*N;
    % 當k小于Ae的長度時,矩陣Ae每10行作為一個音頻資料段存入元胞B中
    while ( k < th )
        i = k : k+9;
        m = (k+9)/10;
        B{m,1} = Ae(i,j);
        k = k+10;
    end      

三、運作結果

【語音隐寫】基于matlab GUI DCT音頻數字水印嵌入提取【含Matlab源碼 837期】

四、matlab版本及參考文獻

​1 matlab版本​

2014a

​2 參考文獻​

[1]韓紀慶,張磊,鄭鐵然.語音信号處理(第3版)[M].清華大學出版社,2019.

繼續閱讀