一、離散小波變換的音頻信号數字水印技術簡介
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版本及參考文獻
1 matlab版本
2014a
2 參考文獻
[1]韓紀慶,張磊,鄭鐵然.語音信号處理(第3版)[M].清華大學出版社,2019.