%FILTER_DESIGN_ZP_CON Design a 2-D zero phase filter by using % the minimax error between the ideal frequency response and the % approximation given by the window method as the design criteria. CON % stands for constrained optimization. % % h = filter_design_zp_unc(Hd,Nfilt_row,Nfilt_col,filename) % Hd: the ideal frequency response % Nfilt_row: vertical order of the output filter % Nfilt_col: horizontal order of the output filter % filename: the full path to the text file containing the constraint % information. The first 2 columns of this text file contains the % locations (horizontal and vertical respectively) of the constraints in % the frequency domain and the third column contains their respected % values. % h: output filter % % This function will also print out the minimax error between the output % filter and the ideal filter. % % Example % -------- % Design a 15x15 lowpass filter based on the ideal frequency response Hd % with the following constraints given in the text file "constraint.txt" % % 0.0 0.0 1.0 % 0.5 0.5 0.0 % % h=filter_design_zp_con(Hd,15,15,'constraint.txt'); % % NOTE: Hd can be designed using the function ideal_response_zp. Please % refer to the help documents of ideal_response_zp for more information. function h = filter_design_nq_con(Hd,Nfilt_row,Nfilt_col,filename) Npt=size(Hd,1); Hd_half = Hd((size(Hd,1)*0.5+1):size(Hd,1),:); %Generate desired window win=ones(Nfilt_row,Nfilt_col); %Generate actual filter response using window method ha = fwind2(Hd,win); a = ha(((size(ha,1)-1)*0.5+1):size(ha,1) ,:); %Extract vector of ind. coefficients ha_vec0 = [reshape(a(2:size(a,1),:),size(a,1)*size(a,2)-size(a,2),1);a(1,(size(a,2)-1)/2+1:size(a,2))']; % %Set optimizing options % options = optimset('MaxFunEvals',5000,'TolFun',1e-10,'TolCon',1e-10,'TolX',1e-5); %Define constraint conditions Aeq and beq such that Aeq.ha_vec=beq %For vectors u and v, run a for loop, each iteration adds a new row to %matrix Aeq tem=textread(filename); u=tem(:,1); v=tem(:,2); beq=tem(:,3); for i=1:length(u) n1=1:1:(Nfilt_col-1)/2; n2=1:1:(Nfilt_row-1)/2; n1_tem=2*cos(2*pi*u(i)*n1);%n2=0; n1=1,...,N1 n1_row=[fliplr(n1_tem) 1 n1_tem];%n2=0; n1=-N1,...,N1 n1=-(Nfilt_col-1)/2:1:(Nfilt_col-1)/2; [n1,n2]=meshgrid(n1,n2); n12_array=2*cos(2*pi*(u(i)*n1+v(i)*n2));%n1=-N1,...N1; n2=1,...,N2 %Generate the half-matrix aeq= [n1_row ; n12_array]; %Convert the half-matrix to a row vector Aeq(i,:)=[reshape(aeq(2:size(aeq,1),:),size(aeq,1)*size(aeq,2)-size(aeq,2),1);aeq(1,(size(aeq,2)-1)/2+1:size(aeq,2))']'; end; p=2; exitcond=0; sol = fmincon(@(ha_vec) p_error(ha_vec,Hd_half,Npt,Nfilt_row,Nfilt_col,2),ha_vec0,[],[],Aeq,beq); error_minimax=minmax_error(sol,Hd_half,Npt,Nfilt_row,Nfilt_col); while not(exitcond) p=p+2; sol_tem = fmincon(@(ha_vec) p_error(ha_vec,Hd_half,Npt,Nfilt_row,Nfilt_col,p),ha_vec0,[],[],Aeq,beq); err_tem=minmax_error(sol_tem,Hd_half,Npt,Nfilt_row,Nfilt_col); if (err_tem>=error_minimax) exitcond=1; p=p-2 else sol=sol_tem; error_minimax=err_tem; end end % %Calculate minimax error % error_minmax = minmax_error(sol,Hd_half,Npt,Nfilt_row,Nfilt_col) error_minimax %Generate full response from vector of solution tem=[fliplr(sol(Nfilt_col*(Nfilt_row-1)/2+2:length(sol))') sol(Nfilt_col*(Nfilt_row-1)/2+1:length(sol))'; reshape(sol(1:Nfilt_col*(Nfilt_row-1)/2),(Nfilt_row-1)/2,Nfilt_col)]; h = [flipud(fliplr(tem(2:size(tem,1),:)));tem]; %%%%%%%%%%%%%Subfunctions to be used above%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Subfunction1: function err = p_error(ha_vec,Hd_half,Npt,Nfilt_row,Nfilt_col,p) %Create the corner quadrants %Convert vector of ind. coefficients to array ha_mat=[fliplr(ha_vec(Nfilt_col*(Nfilt_row-1)/2+2:length(ha_vec))') ha_vec(Nfilt_col*(Nfilt_row-1)/2+1:length(ha_vec))'; reshape(ha_vec(1:Nfilt_col*(Nfilt_row-1)/2),(Nfilt_row-1)/2,Nfilt_col)]; %Create the quadrants of the full response dleft = ha_mat(:,1:(Nfilt_col-1)/2); uright = fliplr(flipud(ha_mat(2:size(ha_mat,1),1:((Nfilt_col-1)*.5+1)))); dright = ha_mat(:,((Nfilt_col-1)*.5 + 1):Nfilt_col); uleft = fliplr(flipud(ha_mat(2:size(ha_mat,1),((Nfilt_col-1)*.5+2):Nfilt_col))); %Pad the actual response to take fft2 ha_pad = [dright zeros(size(dright,1),Npt-Nfilt_col) dleft;zeros(Npt-Nfilt_row,Npt); uright zeros(size(uright,1),Npt-Nfilt_col) uleft]; tem = fft2(ha_pad); Ha_half = [tem(1:Npt/2,Npt/2+1:Npt) tem(1:Npt/2,1:Npt/2)]; %Calculate the p-error err = sum(sum((Ha_half - Hd_half).^p)); %Subfunction 2: function err = minmax_error(ha_vec,Hd_half,Npt,Nfilt_row,Nfilt_col) %Generate full impulse response and frequency response from one quadrant. %Convert vector of ind. coefficients into half of the full response ha_mat=[fliplr(ha_vec(Nfilt_col*(Nfilt_row-1)/2+2:length(ha_vec))') ha_vec(Nfilt_col*(Nfilt_row-1)/2+1:length(ha_vec))'; reshape(ha_vec(1:Nfilt_col*(Nfilt_row-1)/2),(Nfilt_row-1)/2,Nfilt_col)]; %Create the four quadrants of the response dleft = ha_mat(:,1:(Nfilt_col-1)/2); uright = fliplr(flipud(ha_mat(2:size(ha_mat,1),1:((Nfilt_col-1)*.5+1)))); dright = ha_mat(:,((Nfilt_col-1)*.5 + 1):Nfilt_col); uleft = fliplr(flipud(ha_mat(2:size(ha_mat,1),((Nfilt_col-1)*.5+2):Nfilt_col))); %Pad the actual response to take fft2 ha_pad = [dright zeros(size(dright,1),Npt-Nfilt_col) dleft;zeros(Npt-Nfilt_row,Npt); uright zeros(size(uright,1),Npt-Nfilt_col) uleft]; tem = fft2(ha_pad); Ha_half = [tem(1:Npt/2,Npt/2+1:Npt) tem(1:Npt/2,1:Npt/2)]; %Calculate the minimax error err = max(max(abs(Ha_half - Hd_half)));