数字图像处理期末测试

创建以YUVtoJPEG为名称的M文件,读取CIF格式的YUV文件mobile_cif_300f.yuv的前60帧,并逐一以jpg格式保存各视频帧至当前目录下,视频帧帧号命名相对应的jpg图片。保存的jpg图片满足以下条件: 
第1-10帧,视频帧缩小1倍后,利用双线性内插法放大回原尺寸; 
第11-20帧,对视频帧混入椒盐噪声,再作中值滤波; 
第21-30帧,对视频帧混入高斯噪声,再作图像维纳滤波复原;
第31-40帧,对视频帧作直方图均衡化;
第41-50帧,对视频帧作Sobel边缘检测,将边缘点像素值增大为原值的1.2倍;
第51-60帧,将视频帧的DCT变换系数取值前30%置为0,并重建视频帧;
计算第1-60帧处理后视频帧与原始视频帧在Y通道上的PSNR值,并显示出PSNR值随帧号的变化曲线。
注:上述所有处理均在Y通道,UV通道不作处理。
%YUVtoJPEG.m
clc;clear;
%
[Y,U,V] = ReadMultiFrames('mobile_cif_300f.yuv','cif',[0,60]);
len = size(Y,3);
psnr = [];
for ii = 1:len
    Yc = Y(:,:,ii);
    Uc = U(:,:,ii);
    Vc = V(:,:,ii);
    if ii<=10
        Yd = fun1(Yc);
    elseif ii<=20
        Yd = fun2(Yc);
    elseif ii<=30
        Yd = fun3(Yc);
    elseif ii<=40
        Yd = fun4(Yc);
    elseif ii<=50
        Yd = fun5(Yc);
    else
        Yd = fun6(Yc);
    end
    tmp = PSNR(Yc,Yd);
    psnr = [psnr,tmp];
    im_rgb = yuv2rgb(Yd,Uc,Vc);
    imwrite(uint8(im_rgb),[num2str(ii),'.jpg']);
end
plot(psnr);
    
function Yd = fun1(Yc)

w = fspecial('average',[5,5]);
Yc = imfilter(Yc,w);
Yc = Yc(1:2:end,1:2:end);

Yd = imresize(Yc,2,'bilinear');

end
function Yd = fun2(Yc)

Yc = uint8(Yc);
J = imnoise(Yc,'salt & pepper',0.05);
B = ordfilt2(J,13,ones(5,5));
Yd = double(B);

end
function Yd = fun3(Yc)

Yc = mat2gray(Yc);
J = imnoise(Yc,'gaussian',0,0.05);
B = wiener2(J,[5 5]);
Yd = double(255*B);

end
function Yd = fun4(Yc)

Yc = uint8(Yc);
Yd = histeq(Yc);
Yd = double(Yd);

end
function Yd = fun5(Yc)

BW = edge(Yc,'sobel');
Yc(BW(:)) = Yc(BW(:))*1.2;
Yd = Yc;

end
function Yd = fun6(Yc)

d = dct2(Yc);
[tmp,idx] = sort(d(:),'descend');
idx1 = idx(1:round(length(idx)*0.3));
d(idx1) = 0;
Yd = idct2(d);

end
function r = PSNR(x1,x2)

x1 = double(x1);
x2 = double(x2);

mes = x1-x2;

r = 10 * log10(255^2 / mean(mes(:).^2));

end
function im_rgb = yuv2rgb(Yd,Uc,Vc)

Uc = imresize(Uc,2);
Vc = imresize(Vc,2);

R = Yd + 1.4075*(Vc-128);
G = Yd - 0.3455*(Uc-128) - 0.7169*(Vc-128);
B = Yd + 1.7790*(Uc-128);

im_rgb = cat(3,R,G,B);
im_rgb(im_rgb>255) = 255;
im_rgb(im_rgb<0) = 0;

end

  

function [Y,U,V] = ReadMultiFrames(yuvfilename,format,init2last)
%该函数用于将yuv格式的视频连续多帧分别读入到三维数组Y,U,V之中
%yuv视频的采样格式为4:2:0
%输入参数:
%      yuvfilename  ---- 视频yuv文件路径名
%      format       ---- 视频格式(格式名or分辨率[rows,cols])
%      init2last    ----  读取的视频帧的范围[初始帧序号,终止帧序号]
%输出参数:
%         Y         ---- 亮度,三维数组,第三维为帧序号,前两维是单帧的行和列
%        U,V        ---- 色差,三维数组,第三维为帧序号,前两维是单帧的行和列
%调用示范:
%  [Y,U,V] = ReadMultiFrames('.\videoname.yuv','cif',[100,101]);
%  [Y,U,V] = ReadMultiFrames('.\videoname.yuv',[288,352],[100,101]);
close all;
if ischar(format)
    format = lower(format);
    switch format
        case 'sub_qcif'
            cols = 128; rows = 96;
        case 'qcif'
            cols = 176; rows = 144;
        case 'cif'
            cols = 352; rows = 288;
        case 'sif'
            cols = 352; rows = 240;
        case '4cif'
            cols = 704; rows = 576;
        otherwise
            error('no format!');
    end
elseif isequal(size(format),[1,2])||isequal(size(format),[2,1])
    cols = format(2);rows = format(1);
else
    error('第二参数输入有误!');
end


point = fopen(yuvfilename,'r');
if point == -1
    error('打开文件失败!');
end

order_num = init2last(1);
frames_num = init2last(2) - order_num + 1;
k = 0;
Y = zeros(rows,cols,frames_num);
U = zeros(rows/2,cols/2,frames_num);
V = U;

offset = order_num*(rows*cols + rows*cols/2);
status = fseek(point,offset,'bof');
pro = fread(point,1,'uchar');
if (isempty(pro)&&feof(point)) || status ~=0
    error('读取位置定位失败!');
end
fseek(point,-1,'cof');

for ii = 1:frames_num
    k = k + 1;
    pro = fread(point,1,'uchar');
    if feof(point)&&isempty(pro)
        disp('读取帧数范围已超过yuv视频总帧数!');
        Y = Y(:,:,1:k-1);
        U = U(:,:,1:k-1);
        V = V(:,:,1:k-1);
        break;
    end
    fseek(point,-1,'cof');
    temp = fread(point,[cols,rows],'uchar');
    Y(:,:,ii) = temp';
    temp = fread(point,[cols/2,rows/2],'uchar');
    U(:,:,ii) = temp';
    temp = fread(point,[cols/2,rows/2],'uchar');
    V(:,:,ii) = temp';
end

fclose(point);

end

 

你可能感兴趣的:(学习数字图像处理)