计算机图形图像处理基础
练习图片
1.计算机图片原理
黑白模式(单色图像、二值图像):像素只有黑白以及中间的过渡灰色。
图片由黑色区域和白色区域组成。每个像素的值在0-255之间(uint8类型),或0-1之间(double类型);
如,0-1体系里,0(纯黑),1(纯白),0.4,0.78等为灰色。
![](https://pic4.zhimg.com/80/v2-78174fcf9e1823739ce4d77c8e6246af_720w.webp)
按照0-255体系,则有:
RGB彩色模式:每个像素点都有三盏灯RGB,通过RGB三盏灯的亮度就可以组合出该像素点的颜色和亮度!
LED显示器的一个像素的结构。
颜色组合原理:
(1)每一个像素由RGB三个分量组成。
(2)一副彩色数字图像由R, G, B三个通道构成,可以看做一个三维数组。
(2)每个分量各占8位,其范围为0~255,每个像素24位比特(8*3bit,3字节)。
![](https://pic4.zhimg.com/80/v2-c516cabf6145e8d95f3509d3a2fc6e63_720w.webp)
灰度图与rbg彩色图之间的关系;
%手工建立一个灰度十字型
P=[ 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 1 1 1 1 0 0 0 0;
0 0 0 0 1 1 1 1 0 0 0 0;
0 0 0 0 1 1 1 1 0 0 0 0;
0 1 1 1 1 1 1 1 1 1 1 0;
0 1 1 1 1 1 1 1 1 1 1 0;
0 1 1 1 1 1 1 1 1 1 1 0;
0 1 1 1 1 1 1 1 1 1 1 0;
0 0 0 0 1 1 1 1 0 0 0 0;
0 0 0 0 1 1 1 1 0 0 0 0;
0 0 0 0 1 1 1 1 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 ];
imshow(P)
%建立rbg图
P1=P*0.82;
P2=P*0.11;
P3=P*0.66;
P_rgb=cat(3,P1,P2,P3);
imshow(P_rgb)
任务:请把自己的学号的最后一位数字,用上述方式,分别制作成灰度图,以及rgb彩图,并显示。
练习:设计一个3*3*3的3维数组pic,通过imshow( )函数显示pic, 在屏幕上得到一个3行3列(一共9个像素点)的小图片,这个图片上的颜色分布为:
clc
r=[ 0 1 0.5
1 0 0
1 0 1 ]
g=[ 0 1 0.5
0 1 0
1 1 0 ]
b=[ 0 1 0.5
0 0 1
0 1 1 ]
pic=cat(3,r,g,b)
imshow(pic)
2. imshow函数——显示图片
imshow函数:
(1)作用: imshow函数可以把一个二维矩阵(灰度图)或者三维矩阵(彩图)以图片形式显示出来。
(2)处理的数据类型: imshow函数处理的矩阵的数据类型可以是uint8类型(数值范围0-255),和double类型(数值范围0-1)。
% imshow用法
pic1=imread( ' D:\catgray.jpg ' ); %imread读取一个图片,并以矩阵方式存给变量pic
imshow(pic1); %把矩阵pic1(uint8类型)当成图片来显示
size(pic1) %显示矩阵pic的尺寸
%显示矩阵pic的数据类型,默认为uint8类型
pic2=double(pic1)/255; %思考一下为啥要除以255?
imshow(pic2); %把矩阵pic2(double类型)当成图片来显示
whos pic1 pic2 %查看pic1、pic2的数据类型
imtool(pic1); %把矩阵pic当成图片,并用imtool 工具来探索图片信息。
3. 导入图片imread( ) / 输出图片imwrite()
导入图片,imread( )函数用法:
A = imread(filename.fmt) 根据文件名filename读取灰度获彩色图像。返回的数组A包含图像数据。若文件包含灰色图像,A是M*N的数组;若文件名包含真彩图像,A是M*N*3的数组。、
输出图片,imwrite()函数用法:imwrite(pic,'filename'),
一种更常用但仅适用于JPEG图像的imwrite语法是:imwrite(f, 'filename.jpg', quality', q);其中,q是介于0到100的整数(缘于JPEG压缩,q越小,图像的退化就越严重)。仅适用于TIFF图像的更常用的imwrite语法如下:
% 示例:
clc; clear all;
pic1=imread('D:\pic\pic16.jpg'); %从'D:\pic\pic16.jpg'处读入图片给pic1
imshow(pic1) %显示pic1
[r,c,h] = size(pic1) %测量pic1的行数r、列数c、厚度h
pic2=pic1(1:700,1:700,:); %截取pic1的第1-700行,1-700列 ,赋给pic2
imshow(pic2) %显示pic2
pic3=fliplr(pic2); %把pic2左右翻转后赋给pic3
imshow(pic3) %显示pic3
imwrite(pic3,'D:\pic\pic16_new.png') %把 pic3保存为'D:\pic\pic16_new.png'
4. 彩色图/灰度图/二值图的转换
%灰度图与彩色图的关系。
clear all;
pic_rgb=imread('E:\pic8.jpg'); %读入彩色图
[n,m,d]=size(pic_rgb) %测量彩色图的size
pic_r =pic_rgb(:,:,1); %抽取R通道的矩阵给变量pic_r
pic_g=pic_rgb(:,:,2); %抽取G通道的矩阵给变量pic_g
pic_b=pic_rgb(:,:,3); %抽取B通道的矩阵给变量pic_b
pic_gray1=pic_r*0.299 +pic_g*0.587+pic_b*0.114; %利用心理学公式合成
pic_gray2 =pic_r*0.333 +pic_g*0.333+pic_b*0.333; %均值化合成
%显示以上各图
subplot(2,3,1),imshow(pic_rgb);
subplot(2,3,2),imshow(pic_r);
subplot(2,3,3),imshow(pic_g);
subplot(2,3,4),imshow(pic_b);
subplot(2,3,5),imshow(pic_gray1);
subplot(2,3,6),imshow(pic_gray2);
(2)灰度图转二值图
%方法1:for循环
clf
pic_rgb=imread('D:\matlab2021\pic\huoche_rbg.jpg'); %读入彩色图
pic_r =pic_rgb(:,:,1); %抽取R通道的矩阵给变量pic_r
pic_g=pic_rgb(:,:,2); %抽取G通道的矩阵给变量pic_g
pic_b=pic_rgb(:,:,3); %抽取B通道的矩阵给变量pic_b
pic_gray1=pic_r*0.299 +pic_g*0.587+pic_b*0.114; %利用心理学公式合成
pic_bw=pic_gray1; %把pic_gray1复制一份给pic_bw,pic_bw为即将出现的二值图
[row,col]=size(pic_bw) %测量图片的行数,列数
level=median(pic_bw(:)); %把图像所有像素中的中位数当做level值
for n=1:row %历遍所有行
for m=1:col %历遍所有列
if pic_bw(n,m)<=level %如果当前像素小于level值则将其置为0
pic_bw(n,m)=0;
else %如果当前像素大于level值则将其置为255
pic_bw(n,m)=255;
end
end
end
subplot(1,2,1), imshow(pic_gray1)
subplot(1,2,2), imshow(pic_bw)
%方法2:向量化
clf
pic_bw=pic_gray1;
level=median(pic_bw(:));
pic_bw(pic_bw<level)=0;
pic_bw(pic_bw>=level)=255;
imshow(pic_gray1)
imshow(pic_bw)
(3)把灰度图中偶数行与偶数列的点置0
%方法1:双重for循环
clf
pic_0=pic_gray1;
[row,col]=size(pic_0)
for n=1:row
for m=1:col
if mod(n,2)==0|mod(m,2)==0
pic_0(n,m)=0;
end
end
end
imshow(pic_gray1)
imshow(pic_0)
%方法2:单层for循环
clf
pic_0=pic_gray1;
[row,col]=size(pic_0)
for n=2:2:row
pic_0(n,:)=0;
end
for m=2:2:col
pic_0(:,m)=0;
end
imshow(pic_gray1)
imshow(pic_0)
(4)对图像进行反相处理
%对灰度图的反相处理
pic_fx=255-pic_gray1;
imshow(pic_gray1)
imshow(pic_fx)
%对彩色图的反相处理
pic_color_fx=255-pic_rgb;
imshow(pic_rgb)
imshow(pic_color_fx)
(5)图像的Gamma矫正
将灰度过高或者灰度过低的图片进行修正,增强对比度。
试着采用不同伽马值对灰度图进行调整。
clf
Gamma=2; %设置伽马值
pic_Gamma=(double(pic_gray1)/255).^Gamma; %需先把图片矩阵转为double型
imshow(pic_gray1)
imshow(pic_Gamma);
综合练习1:
图像中颜色的替换
要求,把下面左图中的深蓝色替换成如右图所示的油绿色。
油绿色RGB值:
clear all
clf
pic_rgb=imread('E:\pic7.jpg'); %读入彩色图
[n,m,d]=size(pic_rgb) %测量彩色图的size
%查看所选的蓝色纯色部分的,各个通道的亮度值
region_r = pic_rgb(1:50,1:50,1)
region_g= pic_rgb(1:50,1:50,2)
region_b= pic_rgb(1:50,1:50,3)
%求出该块的红通道亮度的最小值r1,最大值r2
r1=min(region_r(:)), r2=max(region_r(:))
%求出该块的绿通道亮度的最小值g1,最大值g2
g1=min(region_g(:)), g2=max(region_g(:))
%求出该块的蓝通道亮度的最小值b1,最大值b2
b1=min(region_b(:)), b2=max(region_b(:))
pic_r = pic_rgb(:,:,1); %抽取R通道的矩阵给变量pic_r
pic_g = pic_rgb(:,:,2); %抽取G通道的矩阵给变量pic_g
pic_b = pic_rgb(:,:,3); %抽取B通道的矩阵给变量pic_b
for i=1:n
for j=1:m
r_logic = ( pic_r(i,j)>=r1&pic_r(i,j)<=r2 );
g_logic = ( pic_g(i,j)>=g1&pic_g(i,j)<=g2 );
b_logic = ( pic_b(i,j)>=b1&pic_b(i,j)<=b2 );
if r_logic & g_logic & b_logic
%整个图片中,红通道中但凡像素亮度在r1-r2之间的点,统统替换成37
%整个图片中,绿通道中但凡像素亮度在g1-g2之间的点,统统替换成61
%整个图片中,蓝通道中但凡像素亮度在b1-b2之间的点,统统替换成36
pic_r(i,j)=37;
pic_g(i,j)=61;
pic_b(i,j)=36;
end
end
end
pic_rgb2=cat(3,pic_r,pic_g,pic_b); %把三个被处理后的通道重新合并成一个三维数组
subplot(1,2,1), imshow(pic_rgb)
subplot(1,2,2), imshow(pic_rgb2)
%方法2:向量化编程
clear all
clf
pic_rgb=imread('E:\pic7.jpg'); %读入彩色图
[n,m,d]=size(pic_rgb) %测量彩色图的size
%查看所选的蓝色纯色部分的,各个通道的亮度值
region_r = pic_rgb(1:50,1:50,1)
region_g= pic_rgb(1:50,1:50,2)
region_b= pic_rgb(1:50,1:50,3)
%求出该块的红通道亮度的最小值r1,最大值r2
r1=min(region_r(:)), r2=max(region_r(:))
%求出该块的绿通道亮度的最小值g1,最大值g2
g1=min(region_g(:)), g2=max(region_g(:))
%求出该块的蓝通道亮度的最小值b1,最大值b2
b1=min(region_b(:)), b2=max(region_b(:))
pic_r = pic_rgb(:,:,1); %抽取R通道的矩阵给变量pic_r
pic_g = pic_rgb(:,:,2); %抽取G通道的矩阵给变量pic_g
pic_b = pic_rgb(:,:,3); %抽取B通道的矩阵给变量pic_b
r_logic = ( pic_r>=r1&pic_r<=r2 );
g_logic= ( pic_g>=g1&pic_g<=g2 );
b_logic= ( pic_b>=b1&pic_b<=b2 );
pic_logic = r_logic & g_logic & b_logic;
pic_r(pic_logic) = 37;
pic_g(pic_logic) = 61;
pic_b(pic_logic) = 36;
pic_rgb2 = cat(3,pic_r,pic_g,pic_b); %把三个被处理后的通道重新合并成一个三维数组
subplot(1,2,1), imshow(pic_rgb)
subplot(1,2,2), imshow(pic_rgb2)
综合练习3:生成随机彩色网格图
要求:生成如下的3*3的彩色网格图,每个网格100*100像素。
教学目标:通过本项目综合掌握随机函数、图形显示与绘图原理、矩阵的赋值等知识点。
(1)矩阵复制:repmat () 函数
B = repmat(A,m,n)
B = repmat(A,[m n])
B = repmat(A,[m n p...])
%repmat 复制矩阵应用案例
A=randi([0,9],2,2)
B=zeros(10,10);
B(1 : 4 , 1 : 6)=repmat(A , 2 , 3);
B
%如果矩阵的一大片需要赋相同的值,则可以直接把某个值赋给矩阵的这个切片。
A=randi([0,9],2,2)
B=zeros(10,10) ;
B(1 : 4 ,1 : 6)=repmat(A , 2 , 3) ;
B(5 : 10 , 1 : 6)=1 ;
B(5 : 10 , 7 : 10)=2 ;
B
(2)随机彩色图的生成:rand()函数
%每个像素点都是随机彩色的随机彩图的生成方法。
clear all
k=100; % k行k列的彩图
%先单独生成3个通道的数据,
r1=rand(k,k);
g1=rand(k,k);
b1=rand(k,k);
%再合并3个二维矩阵为一个三维的rgb矩阵
rgb=cat(3,r1,g1,b1);
imshow(rgb)
%或者用下列方法,更快捷!
k=100;
rgb=rand( k , k , 3 );
imshow(rgb)
%如果想查看每个通道的灰度图,则采用 imshow(rgb2(:,:,1)) imshow(rgb2(:,:,2)) imshow(rgb2(:,:,3))命令
然而,上图虽然是彩色的,但是每个颜色只有一个像素点,该如何让每个色块变成100*100?
(3)3*3网格,每个网格100*100像素的的随机彩色图生成。
方法1:把3*3像素的小彩图,每个像素点都膨胀100倍。
方法2:先随机生成9个100*100像素的纯色图,然后拼接得到成品图案。
方法1:
clear all
n=100; %设置每个基础色块的像素值
o=ones( n , n , 3 ); %初始化rgb三维数组,初始值都设为0
rgb11=o.*rand(1,1,3); %对每个色块随机染色。
rgb12=o.*rand(1,1,3);
rgb13=o.*rand(1,1,3);
rgb14=o.*rand(1,1,3);
rgb21=o.*rand(1,1,3);
rgb22=o.*rand(1,1,3);
rgb23=o.*rand(1,1,3);
rgb24=o.*rand(1,1,3);
rgb31=o.*rand(1,1,3);
rgb32=o.*rand(1,1,3);
rgb33=o.*rand(1,1,3);
rgb34=o.*rand(1,1,3);
rgb41=o.*rand(1,1,3);
rgb42=o.*rand(1,1,3);
rgb43=o.*rand(1,1,3);
rgb44=o.*rand(1,1,3);
rgb=[rgb11,rgb12,rgb13,rgb14;
rgb21,rgb22,rgb23,rgb24;
rgb31,rgb32,rgb33,rgb34;
rgb41,rgb42,rgb43,rgb44];
imshow(rgb)
方法2:
clear all
n=100; %设置每个基础色块的像素值
o=ones( n , n , 3 ); %初始化rgb三维数组,初始值都设为0
color=rand(4,4,3);
rgb11=o.*color(1,1,:); %对每个色块随机染色。
rgb12=o.*color(1,2,:);
rgb13=o.*color(1,3,:);
rgb14=o.*color(1,4,:);
rgb21=o.*color(2,1,:); %对每个色块随机染色。
rgb22=o.*color(2,2,:);
rgb23=o.*color(2,3,:);
rgb24=o.*color(2,4,:);
rgb31=o.*color(3,1,:); %对每个色块随机染色。
rgb32=o.*color(3,2,:);
rgb33=o.*color(3,3,:);
rgb34=o.*color(3,4,:);
rgb41=o.*color(4,1,:); %对每个色块随机染色。
rgb42=o.*color(4,2,:);
rgb43=o.*color(4,3,:);
rgb44=o.*color(4,4,:);
rgb=[rgb11,rgb12,rgb13,rgb14;
rgb21,rgb22,rgb23,rgb24;
rgb31,rgb32,rgb33,rgb34;
rgb41,rgb42,rgb43,rgb44];
imshow(rgb)
方法3:
%膨胀法(把小图的每个像素点膨胀后填充到大图的对应区域内)
clear all
k=4; %设置网格为k*k
n=100; %设置膨胀倍数n
rgb1=rand(k,k,3); %原始的k*k像素的3通道小彩图
imshow(rgb1)
%下面开始膨胀操作。
rgb=zeros( k*n , k*n , 3 ); %初始化rgb三维数组,初始值都设为0
rgb(1:100,1:100,:) =repmat(rgb1(1,1,:),100,100) ;
rgb(1:100,101:200,:)=repmat(rgb1(1,2,:),100,100) ;
rgb(1:100,201:300,:)=repmat(rgb1(1,3,:),100,100);
rgb(1:100,301:400,:)=repmat(rgb1(1,4,:),100,100);
rgb(101:200,1:100,:) =repmat(rgb1(2,1,:),100,100);
rgb(101:200,101:200,:)=repmat(rgb1(2,2,:),100,100);
rgb(101:200,201:300,:)=repmat(rgb1(2,3,:),100,100);
rgb(101:200,301:400,:)=repmat(rgb1(2,4,:),100,100);
rgb(201:300,1:100,:) =repmat(rgb1(3,1,:),100,100);
rgb(201:300,101:200,:)=repmat(rgb1(3,2,:),100,100);
rgb(201:300,201:300,:)=repmat(rgb1(3,3,:),100,100);
rgb(201:300,301:400,:)=repmat(rgb1(3,4,:),100,100);
rgb(301:400,1:100,:) =repmat(rgb1(4,1,:),100,100);
rgb(301:400,101:200,:)=repmat(rgb1(4,2,:),100,100);
rgb(301:400,201:300,:)=repmat(rgb1(4,3,:),100,100);
rgb(301:400,301:400,:)=repmat(rgb1(4,4,:),100,100);
imshow(rgb)
作业1:下图白色背景有某种红色和某种紫色字母等图案,请编程把图中红色和紫色部分的颜色替换成黄色,并且把背景从白色替换成蓝色。
效果如下图:
其中黄色的rgb值为:254,204,17;蓝色背景的rgb值为:47,144,188;
作业2:把两个图像融合到一张图像里。效果如下:
融合前:
融合后:
原理:假如pic1为600*600的图像,pic2也是600*600的图像,那么可以把pic1的第1行像素中的第1,3,5,7..599列的位置替换为pic2的第1行中的第1,3,5,7..599列的位置的像素;然后把pic1的第2行像素中的第2,4,6,8..600列的位置替换为pic2的第2行中的第2,4,6,8..600列的位置的像素;总之,奇数行的话,就把pic1的奇数列的位置像素替换成对应的pic2的像素,偶数行的话,就把pic1的偶数列的位置像素替换成对应的pic2的像素。
作业3:图像的马赛克处理
马赛克的原理,就是把一个区域内的所有像素的值统一成一个值,消除像素之间的差异性。
要求:(1)先把一张彩色图片转换成灰度图。(2)把图片的行数和列数截取为100的整数倍,比如:如果图片大小为630*540,则保留为600*500。(3)把该灰度图按照20*20像素区块进行马赛克化处理。然后显示原图与马赛克化后的对比图。
效果如下图:
作业4:采用for循环生成如下随机n*m格的彩图
功能1:可以自定义n和m的数量,以及每个格子的像素
功能2:通过循环、pause()函数等技巧,来让如上的随机彩图每隔2秒钟刷新一次,刷新得最终次数自己来确定。需要固定图像,既,需要在imshow后面加hold on命令,以保证每次刷新图像的时候,图像位置固定。
....
imshow(rgb2)
pause(2)
hold on
程序暂停功能——pause()函数
pause(n):程序中出现pause(n)时将在继续执行下一条指令前暂停n秒,这里n可以是任意实数。时钟的精度是由MATLAB的工作平台所决定的,绝大多数工作平台都支持0.01秒的时间间隔。
%用法示例
x=linspace(0,9,10);
y=sin(x);
for k=1:10
fprintf('当x=%f ,时,对应的y=%f \n ', x(k),y(k) )
pause(2)
end
扩展(选做):如何改造上面的程序,生产类似如下的图像。
下图1 为10*10的网格图,其中十字架形状是彩色的其他部分是灰度图(或者反之)
下图2中,圆形图案中为彩色,其他部分为灰色,想想该如何设计?大家也可以自己设计图案形状(如椭圆、三角形等)。
上图中,全图为600*600像素,色块格为6*6,每个色块为100*100像素。
提示:当一个点P(x,y)满足方程
或者时,这个点P(x,y)必然位于椭圆(中心点O(x0,y0))或者圆(半径为r, 中心点O(x0,y0))的内部.