数字图像处理编程入门该怎么入门

一个菜鸟的图像处理入门
我的图书馆
一个菜鸟的图像处理入门
本来就是入门的 那就先说下gdi 跟 bmp 这些东西吧。
1 gdi跟bmp
vc里的CDC 也就是设备上下文 相当于c#里的graphics ,也有lineTo等方法。其实我们在c#中使用graphics的时候就已经在使用gdi+了我们却浑然不觉那么gdi到底在哪里呢 试着在c盘搜索gdiplus或者gdi32名字的文件 你应该会找到 就像这个直接删除应该删不掉 不过你可以给他改个名字 别改了自己都搞忘了O(∩_∩)O哈!。 然后你随便运行个程序比如QQ 肿么样Initialization failure:0x0000000E使用windows自带的图片查看器 加载 c:\windows\system32\shimgvw.dll时出错 系统找不到指定的文件。所以说windows下到处都是gdi不要以为bitmap是一种图像格式 就像jpg gif 一样 实际上他们是两个完全不同的概念。在vc++里叫cbitmap 也就是对应的gdi数据模型 等同于c#里的bitmap 可以这样说.bmp的位图文件是gdi的文件表现形式。 位图文件不进行图像压缩算法操作直接存储像素矩阵信息所以文件体积非常大 jpg文件体积非常小为什么 jpg实际上它是按照完全不同的算法跟理念来存储图像的 都知道人的视觉效应主要体现在两个方面 色彩的明暗度 色彩的饱和度 也就是色调(说俗点就是赤橙黄绿青蓝紫 )并且肉眼根本达不到每个像素那么大的分辨能力 jpg就是按照这种方式来存储的
2 位图文件格式
那么就先说下bmp文件格式吧,本人不是那种长篇大论型的 不说废话。这个压缩包里工程的bin目录有一个叫bmpTestImg.bmp两色的位图文件。以16进制编辑器打开对照下图看 :这里是vc++里有定义好的bitmapheader 用来表示位图头信息 在C#里没有。其实没多大关系的这只是一种数据组织方式如果你愿意也可以定义这么一个结构。gdi与设备无关 但是他并不代表跟设备没有任何关联 计算机之间传递的是图片文件或者图像数据 并不是gdi对象。微软帮我们搞了这一层东西,就是说只要是接入windows的设备我们都可以通过gdi在那个设备上显示 输出东西 而不用关系设备本身 ,可以说整个windows提供给我们的就是gdi 所有窗体 等等都是gdi绘制的,比如说做啥xx编程的时候要直接操纵显卡 实际上直接操纵的方式速度更快但是没有必要所谓的24位真彩色 mspaint画图新建图像默认存储 就是24位真彩色 这并不是什么高深技术因为 一个像素的颜色用3个八位来表示就是24位真彩色 真彩图像是说他具有显示 256x256x256种颜色的能力还有就是c#里默认新建的bitmap对象就是24位真彩的 并且graphic提供的函数不能操作非真彩色的位图
3 水平不咋滴,还是来敲点代码吧,\(^o^)/~
先卖个关子哈 上面你下载的示例图片你看到东西了吗 还是黑乎乎一片 嘿嘿。如果你看到了那你见鬼了 还是赶快拜拜春哥吧最近在研究那啥dicom 也学会拽文了 嘿嘿是否可以这么描述:bmp是一种约定俗成的有规律的数据组织方式 不论他在内存中 在文件中 他跟特定编程语言无关 跟平台无关bmp格式简而言之一句话 前54字节存储文件头信息最主要就是图像位数跟宽度高度,从54位开始有调色板则是调色板信息 无调色板则是像素数据。由于本文不是专门探讨bmp文件格式 详细请参见好下面我们就来读取这种有规律的数据: 写第一个按钮事件的代码
1234567891011121314151617181920212223242526272829303132void bmpRead(){&&&&Image bmp = (Bitmap)Image.FromFile("bmpTestImg.bmp");&&&&&MemoryStream bmpData = new MemoryStream();&&&&bmp.Save(bmpData, ImageFormat.Bmp);&&&&BinaryReader br = new BinaryReader(bmpData);&&&&&&&&bmpData.Seek(18, SeekOrigin.Begin);&&&&int width = br.ReadInt32();&&&&int height = br.ReadInt32();&&&&MessageBox.Show(string.Format("宽{0},高{1}", width, height));&&&&&&&&bmpData.Seek(10, SeekOrigin.Begin);&&&&int dataStart = br.ReadInt32();&&&&&byte[] datas = new byte[width * height];&&&&int indx = 0;&&&&bmpData.Seek(dataStart, SeekOrigin.Begin);&&&&&&&&bmpData.Seek(54, SeekOrigin.Begin);&&&&Random rd = new Random();&&&&bmpData.Write(new byte[] { (byte)rd.Next(0, 255), (byte)rd.Next(0, 255), &&&&&&&&(byte)rd.Next(0, 255), 0 }, 0, 4);&&&&bmpData.Write(new byte[] { (byte)rd.Next(0, 255), (byte)rd.Next(0, 255), &&&&&&&&(byte)rd.Next(0, 255), 0 }, 0, 3);&&&&&Image newbmp = Bitmap.FromStream(bmpData);&&&&Graphics.FromHwnd(this.Handle).DrawImage(newbmp, new Point(0, 0));&&&&bmpData.Close();&&&&br.Close();}
上面的代码很简单滴 (⊙o⊙)哦 都看得懂吧 别忘了要在执行文件同级目录放上偶的图片哦 嘿嘿。这个适合用来给girlfriend表白啊啥的O(∩_∩)O哈!有几个需要说明的地方 bmp文件的两色 并非一定得是黑白 对吧& 可以是红色绿色, 也可以是两种相同的色儿 对吧 为什么宽度要在第19字节的位置开始存储 没有为什么 这是bmp格式的“龟腚”对吧 要问去问盖茨大叔 对于“流”的操作 seek到前面去了 再进行write操作 是否就把对应位置的数据“挤”到后面去了呢?NO 数据流是一种游标 “覆盖”型的操作 长度会自动标识到游标到过最远的地方 文件流内存流都一样 所以说想要做数据插入啊 文件合并啊之类的东东的话得弄两个数据流对象哈 互相倒腾数据 这样才能达到目的。又扯远了哈 打住。不是说读取数据吗 就是读取像素值数据啊,现在开始& 既然是读取像素值,咱得一行一行的读啊 就像扫描一样的。实际上他就是以这种方式存储的哈 只不过稍微有点不一样那就是图像数据每行以四倍字节为基数不足以0补齐 乃明白了木有 。比如说这一个扫描行有3个像素 那么就是9字节 ,4字节的倍数那么他必须要有12字节 那么剩下的3字节全是0。比如说这一个扫描行有20个像素 那么就是60字节 ,4字节的倍数那么他必须要有60字节 因为60/4正好除净。先来说下这个破公式 ((width * 24 + 31) / 32 * 4) 不知道是哪个头脑发热的人想出来的 ,注意这里的32是指32位 即4字节。实际上我只想说两个字非常扯淡 一定是很深入的掌握了数据长度运算的本质, 一句把我上面那n多句都代替了width是图像宽度 24代表每个像素位数。 计算出实际字节数 先假设他会超出一位 补齐31位 然后通过整型数据相除的性质 除以4字节得到4字节的倍数 注意最终得到的是扫描行的字节数就这样从图像左下角第一个点开始 一行一行从左至右的往上扫描然后是bmp图像素的存储方式是BGR的顺序哈 而不是通常的RGB 哦 别搞错了,以前很菜的时候用SetPixel()处理像素 被人骂惨了 现在俺依然来写个setPix() 嘿嘿 第二个按钮的代码:
1234567891011121314151617181920212223242526272829303132333435363738void setPix(){&&&&FileStream bmpData = File.Open("mm.bmp", FileMode.Open); BinaryReader br = new BinaryReader(bmpData);&&&&bmpData.Seek(10, SeekOrigin.Begin);int bmpDataStart = br.ReadInt32();&&&&bmpData.Seek(18, SeekOrigin.Begin);int width = br.ReadInt32();int height = br.ReadInt32();&&&&&Bitmap newBmp = (Bitmap)new Bitmap(width, height, PixelFormat.Format24bppRgb);&&&&MemoryStream newBmpData = new MemoryStream();&&&&newBmp.Save(newBmpData, ImageFormat.Bmp);BinaryReader br2 = new BinaryReader(newBmpData);&&&&newBmpData.Seek(10, SeekOrigin.Begin); int newBmpDataStart = br2.ReadInt32();&&&&newBmpData.Seek(newBmpDataStart, SeekOrigin.Begin);&&&&&for (int i = 0; i & i++)&&&&{&&&&&&&&bmpData.Seek(((width * 24 + 31) / 32 * 4) * i + bmpDataStart, SeekOrigin.Begin);&&&&&&&&newBmpData.Seek(((width * 24 + 31) / 32 * 4) * i + newBmpDataStart, SeekOrigin.Begin);&&&&&&&&for (int j = 0; j & j++)&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&byte[] data = new byte[3];&&&&&&&&&&&&bmpData.Read(data, 0, 3);&&&&&&&&&&&&newBmpData.Write(new byte[] { data[2], data[1], data[0] }, 0, 3);&&&&&&&&&&&&&&&&&& &&&&&&&&}&&&&&&&&&&&&&&&&int fill = ((width * 24 + 31) / 32 * 4) - width * 3;&&&&&&&&if (fill & 0)&&&&&&&&{&&&&&&&&&&&&byte[] fills = new byte[] { 0, 0, 0 };&&&&&&&&&&&&newBmpData.Write(fills, 0, fills.Length);&&&&&&&&}&&&&}&&&&newBmpData.Flush();&&&&newBmp = (Bitmap)Bitmap.FromStream(newBmpData);&&&&Graphics.FromHwnd(this.Handle).DrawImage(newBmp, new Point(0, 0));&&&&&bmpData.Close(); newBmpData.Close();&&&&br.Close(); br2.Close();}
如果你把for (int i = 0; i & i++)改成&for (int i = 0; i & height/2; i++) 可以看下效果 可以证明在文件中是按照图像从左至右往上 的方式存储的通过以上可以看出任何环境下他都是按照同种规律存储存储的,就像dicom 只要遵循这种规律就能通过这种格式实现数据共享。都说lockBitmap的方式是最快的 ,确实是最快的哈 因为他是使用指针的方式下面是把一个图像转成灰度图 你看 不但代码少了很多 并且还不用费尽心思去确定每一个扫描行的索引 你看 刷的一下 就出来了 嘿嘿注意有unsafe代码 在项目-&属性 勾选“允许不安全代码” :
12345678910111213141516171819202122232425void lockPix(){&&&&Bitmap bmp = (Bitmap)Image.FromFile("mm.bmp");&&&&BitmapData datas = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), &&&&&&&&System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);&&&&unsafe&&&&{&&&&&&&&byte* p = (byte*)datas.Scan0;&&&&&&&&int indx = 0;&&&&&&&&for (int i = 0; i & bmp.Height/2; i++)&&&&&&&&{&&&&&&&&&&&&for (int j = 0; j & bmp.W j++)&&&&&&&&&&&&{&&&&&&&&&&&&&&&&byte b, g, b = p[indx + 1]; g = p[indx + 2]; r = p[indx + 3];&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&byte gray = (byte)((r + g + b) / 3);&&&&&&&&&&&&&&&&p[indx++] = p[indx++] = p[indx++] =&&&&&&&&&&&&}&&&&&&&&}&&&&}&&&&&bmp.UnlockBits(datas);&&&&Graphics.FromHwnd(this.Handle).DrawImage(bmp, new Point(0, 0));&&&&bmp.Dispose();}
灰度图 哎呀 跟你说得又俗又土点就是对每个像素 rgb三个值加起来除以3& 不想跟你讲那些我自己都不怎么明白的东西但是还是不得不跟你说下所谓的yuv表示方式& y代表明度 说到这个又得要讲下矩阵乘法 真麻烦ya。这个什么意思呢,先说说矩阵乘法吧比如你商店里有帽子鞋子 袜子 单价分别表示为:[25] [80] [15]然后今天帽子卖了3件 鞋子卖了1件 袜子卖了两件,可表示为:[3][1][2]然后今天的收入呢=25x3+80x1+15x2 总共185 用矩阵表示为[185]我第二天帽子卖了1件 鞋子卖了两件 袜子卖了3件,那么这两天的销售可表示为:[3] [1][1] [2][2] [3]那么这两天总共的收入呢=(25x3+80x1+15x2)+(25x1+80x2+15x3) 总共185+230=415 用矩阵表示为[185][230]没错 你看到的这就是矩阵乘法 不想讲什么线性代数 什么的那么高深的理论比如上面RGB转转YUV公式的3行3列 乘 3行1列 乘出来是 3行1列 ,规律就是第一个矩阵的列跟第二个矩阵的行一致,得到一个首行尾列数的二维矩阵。如果rgb值分别是{115,20,65} 那么转换成yuv表示应该是y=115x0.299+20x0.587+65x0.114u=115x-0.148+20x-0.289+65x0.437v=115x0.615+20x-0.515+65x-0.1貌似很难理解 因为这个跟前面那个卖东西的又不一样了可以换个角度看 。把第二个矩阵往左“倒下来” 就是说让他的行跟第一个矩阵的列 对齐 是不是感觉好多了O(∩_∩)O哈!整点复杂的 那再来随便整个吧[2] [4]&&&&& [-1] [6][1] [0]&&&&& [3 ] [5]结果是多少2x-1+4x3&&&&& 2x6+4x51x-1+0x3&&&&& 1x6+0x5最终结果[10]&&&&& [32][-1]&&&&& [6]也可以把它分解为单行单列的来看 就简单多了哈有种很特殊的矩阵 有点像对角线 任何跟他相乘的矩阵都等于那个矩阵本身 有点像 “任何数乘以1 都等于那个数本身”[1][0][0][1]看吧矩阵乘法就是这么神奇的东东,通过矩阵乘法还可以进行角度旋转 缩放等等& 这个是很高深的研究课题了O(∩_∩)O哈! 这里就不讨论了终于说完了 俺喝口水了先。也不知讲清楚了没 下面是各种矩阵乘法的示例代码 关于为什么是5x5的矩阵这个可以看下:知识学无止境第三个按钮:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647void matrixColor(){&&&&Bitmap bmp = (Bitmap)Image.FromFile("mm.bmp");&&&&ImageAttributes ia = new ImageAttributes();&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&float[][] colorMatrix ={&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&new float[]{1,&&&& 0,&&&&& 0,&&&&& 0,& 0},&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&new float[]{0,&&&& 1,&&&&& 0,&&&&& 0,& 0},&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&new float[]{0,&&&& 0,&&&&& 1,&&&&& 0,& 0},&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&new float[]{0,&&&& 0,&&&&& 0,&&&&& 1,& 0},&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&new float[]{l,&&&& l,&&&&& l,&&&&& 0,& 1}};&&&&l -= 0.1f;&&&&&ColorMatrix cm = new ColorMatrix(colorMatrix);&&&&ia.SetColorMatrix(cm, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);&&&&Graphics.FromHwnd(this.Handle).DrawImage(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height),&&&&&&&&0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, ia);&}float l = 0.5f;
&rgb为3个能量值 我们看到屏幕上花花绿绿 颜色是因为三个能量值产生差异化 说俗点就是三个值的比例不一样 如果三个值一样的话那就跟电灯泡无异了 就是纯亮度表示 即我们常说的灰度图。来写个手工滴 很山寨滴 效率很低滴 更改亮度的函数
1234567891011121314151617181920212223void light(ref int r, ref int g, ref int b){&&&&&&&&&&&&float gray= (r + g + b) + level * 90 & 255 * 3 ? 255 * 3 : (r + g + b) + level * 90;&&&&&&&&&&&&float percentR = (float)r / (r + g + b), percentG = (float)g / (r + g + b), percentB = (float)b / (r + g + b);&&&&&r = (int)(gray * percentR & 255 ? 255 : gray * percentR);&&&&g = (int)(gray * percentG & 255 ? 255 : gray * percentG);&&&&b = (int)(gray * percentB & 255 ? 255 : gray * percentB);&&&&&float ren = gray - (r + g + b);&&&&if (ren &= 3)&&&&{&&&&&&&&r = (r + (int)ren) & 255 ? 255 : (r + (int)ren);&&&&&&&&g = (g + (int)ren) & 255 ? 255 : (g + (int)ren);&&&&&&&&b = (b + (int)ren) & 255 ? 255 : (b + (int)ren);&&&&}&}int level = 0;
&其实呢也远可以不必这样 直接rgb分别乘以1.2 或者1.1之类的就可以了 只不过颜色会失真
&好了终于写完啦 好累ya
完了 ( ⊙ o ⊙ ) 本来就很菜 这点破秘密全被你们晓得了 以后出去俺还杂混呐当然作为一个商业化的软件 代码的容错也是很重要的 你看acdsee 你把文件数据部分删除一些他照样能够显示 当然这些都是很简单的哈。
TA的最新馆藏
喜欢该文的人也喜欢数字图像处理的基本原理和常用方法
&& 数字图像处理是指将图像信号转换成数字信号并利用计算机对其进行处理的过程。图像处理最早出现于 20 世纪 50 年代,当时的电子计算机已经发展到一定水平,人们开始利用计算机来处理图形和图像信息。数字图像处理作为一门学科大约形成于 20 世纪 60 年代初期。早期的图像处理的目的是改善图像的质量,它以人为对象,以改善人的视觉效果为目的。图像处理中,输入的是质量低的图像,输出的是改善质量后的图像,常用的图像处理方法有图像增强、复原、编码、压缩等。
数字图像处理常用方法:
1 )图像变换:由于图像阵列很大,直接在空间域中进行处理,涉及计算量很大。因此,往往采用各种图像变换的方法,如傅立叶变换、沃尔什变换、离散余弦变换等间接处理技术,将空间域的处理转换为变换域处理,不仅可减少计算量,而且可获得更有效的处理(如傅立叶变换可在频域中进行数字滤波处理)。目前新兴研究的小波变换在时域和频域中都具有良好的局部化特性,它在图像处理中也有着广泛而有效的应用。
2 )图像编码压缩:图像编码压缩技术可减少描述图像的数据量(即比特数),以便节省图像传输、处理时间和减少所占用的存储器容量。压缩可以在不失真的前提下获得,也可以在允许的失真条件下进行。编码是压缩技术中最重要的方法,它在图像处理技术中是发展最早且比较成熟的技术。
3 )图像增强和复原:图像增强和复原的目的是为了提高图像的质量,如去除噪声,提高图像的清晰度等。图像增强不考虑图像降质的原因,突出图像中所感兴趣的部分。如强化图像高频分量,可使图像中物体轮廓清晰,细节明显;如强化低频分量可减少图像中噪声影响。图像复原要求对图像降质的原因有一定的了解,一般讲应根据降质过程建立“降质模型”,再采用某种滤波方法,恢复或重建原来的图像。
4 )图像分割:图像分割是数字图像处理中的关键技术之一。图像分割是将图像中有意义的特征部分提取出来,其有意义的特征有图像中的边缘、区域等,这是进一步进行图像识别、分析和理解的基础。虽然目前已研究出不少边缘提取、区域分割的方法,但还没有一种普遍适用于各种图像的有效方法。因此,对图像分割的研究还在不断深入之中,是目前图像处理中研究的热点之一。
5 )图像描述:图像描述是图像识别和理解的必要前提。作为最简单的二值图像可采用其几何特性描述物体的特性,一般图像的描述方法采用二维形状描述,它有边界描述和区域描述两类方法。对于特殊的纹理图像可采用二维纹理特征描述。随着图像处理研究的深入发展,已经开始进行三维物体描述的研究,提出了体积描述、表面描述、广义圆柱体描述等方法。
6 )图像分类(识别):图像分类(识别)属于模式识别的范畴,其主要内容是图像经过某些预处理(增强、复原、压缩)后,进行图像分割和特征提取,从而进行判决分类。图像分类常采用经典的模式识别方法,有统计模式分类和句法(结构)模式分类,近年来新发展起来的模糊模式识别和人工神经网络模式分类在图像识别中也越来越受到重视。
图像的基本属性
&& 亮度:也称为灰度,它是颜色的明暗变化,常用 0 %~ 100 % ( 由黑到白 ) 表示。以下三幅图是不同亮度对比。
亮度对图像色彩的影响
&& 对比度:是画面黑与白的比值,也就是从黑到白的渐变层次。比值越大,从黑到白的渐变层次就越多,从而色彩表现越丰富。
对比度对图像色彩表现的影响
&& 直方图:表示图像中具有每种灰度级的象素的个数,反映图像中每种灰度出现的频率。图像在计算机中的存储形式,就像是有很多点组成一个矩阵,这些点按照行列整齐排列,每个点上的值就是图像的灰度值,直方图就是每种灰度在这个点矩阵中出现的次数。我们可以具体看一下下面两个不同图形的灰度直方图:
直方图均衡化
&& 通过灰度变换将一幅图像转换为另一幅具有均衡直方图的图像,即在一定灰度范围内具有相同的象素点数的图像的过程。下面是直方图均衡化前后的图形变化以及直方图变化:
图像的加减运算
&& 两幅图像的加减运算:对图像进行加减运算,就是将图像对应的存储矩形点列上的灰度值进行加减运算。图像相加可以将一幅图像的内容加到另一幅图像上,可以实现二次曝光,也可一对同一个场景的多幅图像求平均值,这样可以降低噪声。图像相减可以用于运动检测或去除图像中不需要的加性图案。
&& 图像的加法示例:图中运算为: (a)+(b)=(c)
&& 图像的减法运算示例:图中运算为 (a)-(b)=(c)
图像的噪声
&& 图像的噪声:就像对于听觉而言,在打电话时对方说话我们有时候会听到很嘈杂的噪声,以至于听不清楚对方在说什么。同样的,对于图像,原本我们可以很清晰的看到一幅图像,但是有时候图像上会有一些我们不需要的图案,使我们无法很清楚的看清一幅图,这就是图像的噪声。
常用的图像去噪声方法
&& 常用的去噪方法:主要是采用滤波器对带噪声图像进行滤波处理。
带噪声的图
算术平均滤波后的图
中值滤波后的图
数字图像处理技术的应用
&& 随着计算机技术的发展,图像处理技术已经深入到我们生活中的方方面面,其中,在娱乐休闲上的应用已经深入人心。图像处理技术在娱乐中的应用主要包括:电影特效制作、电脑电子游戏、数码相机、视频播放、数字电视等
&& 电影特效制作:自从 20 世纪 60 年代以来,随着电影中逐渐运用了计算机技术,一个全新的电影世界展现在人们面前,这也是一次电影的革命。越来越多的计算机制作的图像被运用到了电影作品的制作中。其视觉效果的魅力有时已经大大超过了电影故事的本身。如今,我们已经很难发现在一部电影中没有任何的计算机数码元素。
&& 电脑电子游戏:电脑电子游戏的画面,是近年来电子游戏发展最快的部分之一。从 1996 年到现在,游戏画面的进步简直可以用突飞猛进来形容,随着图像处理技术的发展,众多在几年前无法想象的画面在今天已经成为了平平常常的东西。
&& 数码相机:所谓数码相机,是一种能够进行拍摄,并通过内部处理把拍摄到的景物转换成以数字格式存放图像的特殊照相机。与普通相机不同,数码相机并不使用胶片,而是使用固定的或者是可拆卸的半导体存储器来保存获取的图像。数码相机可以直接连接到计算机、电视机或者打印机上。在一定条件下,数码相机还可以直接接到移动式电话机或者手持 PC 机上。由于图像是内部处理的,所以使用者可以马上检查图像是否正确,而且可以立刻打印出来或是通过电子邮件传送出去。
&& 视频播放与数字电视:家庭影院中的 VCD , DVD 播放器和数字电视中,大量使用了视频编码解码等图像处理技术,而视频编码解码等图像处理技术的发展,也推动了视频播放与数字电视象高清晰,高画质发展。已有一些基础的要研究图像处理该如何起步? | 问答 | 问答 | 果壳网 科技有意思
已有一些基础的要研究图像处理该如何起步?
呃,这是一个标题党,点进来才发现这是一个新人求带的贴唔,即将成年大一小码农一枚。熟悉的语言是C++和Python,MATLAB也会一点。不排斥学新语言。对AI很有兴趣,目前正不知死活地奔腾在图像处理的路上希望能有一个比较可行的学习历程,希望各位帮帮忙不然各位大牛给个当年自己学习的书单就好了或者扯些自己的看法也是好的
狭义的图像处理,应该指去噪,分割,边缘检测,图像增强一类吧。基础知识的话冈萨雷斯的那本图像处理应该比较全了。要想再深入,就不是我的专业了。学图像处理的,肯定还会学模式识别吧,看你的标签里也有人工智能。如果你是想做人脸识别,目标识别,图像分类什么的,其实用的模式识别的知识会多过图像处理的。不过这门课我记得我们是大三才学的。入门可以看清华的那本模式识别的教材,然后就是那本希腊人Theodoridis的模式识别,讲的都是最基本的模式识别算法了。更难的可以看Bishop的pattern recognition and machine learning,不过不是为了读博的话,应该没人会去啃这本书吧。大一的话矩阵(线性代数?)跟概率一定要学好哦。模式识别基本上就是各种概率在折腾。话说现在的学生这么厉害啊,大一就懂C++,python,matlab,当年我大一学c语言的时候完全连编程的概念都没有
(C)2017果壳网&&&&京ICP证100430号&&&&京网文[-239号&&&&新出发京零字东150005号&&&&
违法和不良信息举报邮箱:&&&&举报电话:748被浏览58265分享邀请回答19924 条评论分享收藏感谢收起212 条评论分享收藏感谢收起查看更多回答Python图像处理库Pillow入门 - Python - 伯乐在线
& Python图像处理库Pillow入门
Pillow是Python里的图像处理库(PIL:Python Image Library),提供了了广泛的文件格式支持,强大的图像处理能力,主要包括图像储存、图像显示、格式转换以及基本的图像处理操作等。
1)使用 Image 类
PIL最重要的类是 Image class, 你可以通过多种方法创建这个类的实例;你可以从文件加载图像,或者处理其他图像, 或者从 scratch 创建。
要从文件加载图像,可以使用open( )函数,在Image模块中:
&&& from PIL import Image
&&& im = Image.open("E:/photoshop/1.jpg")
&&& from PIL import Image&&& im = Image.open("E:/photoshop/1.jpg")
加载成功后,将返回一个Image对象,可以通过使用示例属性查看文件内容:
&&& print(im.format, im.size, im.mode)
('JPEG', (600, 351), 'RGB')
&&& print(im.format, im.size, im.mode)('JPEG', (600, 351), 'RGB')&&&
format 这个属性标识了图像来源。如果图像不是从文件读取它的值就是None。size属性是一个二元tuple,包含width和height(宽度和高度,单位都是px)。 mode 属性定义了图像bands的数量和名称,以及像素类型和深度。常见的modes 有 “L” (luminance) 表示灰度图像, “RGB” 表示真彩色图像, and “CMYK” 表示出版图像。
如果文件打开错误,返回 IOError 错误。
只要你有了 Image 类的实例,你就可以通过类的方法处理图像。比如,下列方法可以显示图像:
2)读写图像
PIL 模块支持大量图片格式。使用在 Image 模块的 open() 函数从磁盘读取文件。你不需要知道文件格式就能打开它,这个库能够根据文件内容自动确定文件格式。要保存文件,使用 Image 类的 save() 方法。保存文件的时候文件名变得重要了。除非你指定格式,否则这个库将会以文件名的扩展名作为格式保存。
加载文件,并转化为png格式:
"Python Image Library Test"
from PIL import Image
import sys
for infile in sys.argv[1:]:
f,e = os.path.splitext(infile)
outfile = f +".png"
if infile != outfile:
Image.open(infile).save(outfile)
except IOError:
print("Cannot convert", infile)
12345678910111213
"Python Image Library Test"from PIL import Imageimport osimport sys&for infile in sys.argv[1:]:&&&&f,e = os.path.splitext(infile)&&&&outfile = f +".png"&&&&if infile != outfile:&&&&&&&&try:&&&&&&&&&&&&Image.open(infile).save(outfile)&&&&&&&&except IOError:&&&&&&&&&&&&print("Cannot convert", infile)
save() 方法的第二个参数可以指定文件格式。
3)创建缩略图
缩略图是网络开发或图像软件预览常用的一种基本技术,使用Python的Pillow图像库可以很方便的建立缩略图,如下:
# create thumbnail
size = (128,128)
for infile in glob.glob("E:/photoshop/*.jpg"):
f, ext = os.path.splitext(infile)
img = Image.open(infile)
img.thumbnail(size,Image.ANTIALIAS)
img.save(f+".thumbnail","JPEG")
# create thumbnailsize = (128,128)for infile in glob.glob("E:/photoshop/*.jpg"):&&&&f, ext = os.path.splitext(infile)&&&&img = Image.open(infile)&&&&img.thumbnail(size,Image.ANTIALIAS)&&&&img.save(f+".thumbnail","JPEG")
上段代码对photoshop下的jpg图像文件全部创建缩略图,并保存,glob模块是一种智能化的文件名匹配技术,在批图像处理中经常会用到。
注意:Pillow库不会直接解码或者加载图像栅格数据。当你打开一个文件,只会读取文件头信息用来确定格式,颜色模式,大小等等,文件的剩余部分不会主动处理。这意味着打开一个图像文件的操作十分快速,跟图片大小和压缩方式无关。
4)图像的剪切、粘贴与合并操作
Image 类包含的方法允许你操作图像部分选区,PIL.Image.Image.crop 方法获取图像的一个子矩形选区,如:
# crop, paste and merge
im = Image.open("E:/photoshop/lena.jpg")
box = (100,100,300,300)
region = im.crop(box)
# crop, paste and mergeim = Image.open("E:/photoshop/lena.jpg")box = (100,100,300,300)region = im.crop(box)
矩形选区有一个4元元组定义,分别表示左、上、右、下的坐标。这个库以左上角为坐标原点,单位是px,所以上诉代码复制了一个 200×200 pixels 的矩形选区。这个选区现在可以被处理并且粘贴到原图。
region = region.transpose(Image.ROTATE_180)
im.paste(region, box)
region = region.transpose(Image.ROTATE_180)im.paste(region, box)
当你粘贴矩形选区的时候必须保证尺寸一致。此外,矩形选区不能在图像外。然而你不必保证矩形选区和原图的颜色模式一致,因为矩形选区会被自动转换颜色。
5)分离和合并颜色通道
对于多通道图像,有时候在处理时希望能够分别对每个通道处理,处理完成后重新合成多通道,在Pillow中,很简单,如下:
r,g,b = im.split()
im = Image.merge("RGB", (r,g,b))
r,g,b = im.split()im = Image.merge("RGB", (r,g,b))
对于split( )函数,如果是单通道的,则返回其本身,否则,返回各个通道。
6)几何变换
对图像进行几何变换是一种基本处理,在Pillow中包括resize( )和rotate( ),如用法如下:
out = im.resize((128,128))
out = im.rotate(45)
# degree conter-clockwise
out = im.resize((128,128))out = im.rotate(45)&&# degree conter-clockwise
其中,resize( )函数的参数是一个新图像大小的元祖,而rotate( )则需要输入顺时针的旋转角度。在Pillow中,对于一些常见的旋转作了专门的定义:
out = im.transpose(Image.FLIP_LEFT_RIGHT)
out = im.transpose(Image.FLIP_TOP_BOTTOM)
out = im.transpose(Image.ROTATE_90)
out = im.transpose(Image.ROTATE_180)
out = im.transpose(Image.ROTATE_270)
out = im.transpose(Image.FLIP_LEFT_RIGHT)out = im.transpose(Image.FLIP_TOP_BOTTOM)out = im.transpose(Image.ROTATE_90)out = im.transpose(Image.ROTATE_180)out = im.transpose(Image.ROTATE_270)
7)颜色空间变换
在处理图像时,根据需要进行颜色空间的转换,如将彩色转换为灰度:
cmyk = im.convert("CMYK")
gray = im.convert("L")
cmyk = im.convert("CMYK")gray = im.convert("L")
8)图像滤波
图像滤波在ImageFilter 模块中,在该模块中,预先定义了很多增强滤波器,可以通过filter( )函数使用,预定义滤波器包括:
BLUR、CONTOUR、DETAIL、EDGE_ENHANCE、EDGE_ENHANCE_MORE、EMBOSS、FIND_EDGES、SMOOTH、SMOOTH_MORE、SHARPEN。其中BLUR就是均值滤波,CONTOUR找轮廓,FIND_EDGES边缘检测,使用该模块时,需先导入,使用方法如下:
from PIL import ImageFilter
imgF = Image.open("E:/photoshop/lena.jpg")
outF = imgF.filter(ImageFilter.DETAIL)
conF = imgF.filter(ImageFilter.CONTOUR)
edgeF = imgF.filter(ImageFilter.FIND_EDGES)
imgF.show()
outF.show()
conF.show()
edgeF.show()
12345678910
from PIL import ImageFilter&imgF = Image.open("E:/photoshop/lena.jpg")outF = imgF.filter(ImageFilter.DETAIL)conF = imgF.filter(ImageFilter.CONTOUR)edgeF = imgF.filter(ImageFilter.FIND_EDGES)imgF.show()outF.show()conF.show()edgeF.show()
除此以外,ImageFilter模块还包括一些扩展性强的滤波器:
class PIL.ImageFilter.GaussianBlur(radius=2)
Gaussian blur filter.
radius – Blur radius.
class PIL.ImageFilter.UnsharpMask(radius=2, percent=150, threshold=3)
Unsharp mask filter.
See Wikipedia’s entry on
for an explanation of the parameters.
class PIL.ImageFilter.Kernel(size, kernel, scale=None, offset=0)
Create a convolution kernel. The current version only supports 3×3 and 5×5 integer and floating point kernels.
In the current version, kernels can only be applied to “L” and “RGB” images.
size – Kernel size, given as (width, height). In the current version, this must be (3,3) or (5,5).
kernel – A sequence containing kernel weights.
scale – Scale factor. If given, the result for each pixel is divided by this value. the default is the sum of the kernel weights.
offset – Offset. If given, this value is added to the result, after it has been divided by the scale factor.
class PIL.ImageFilter.RankFilter(size, rank)
Create a rank filter. The rank filter sorts all pixels in a window of the given size, and returns therank‘th value.
size – The kernel size, in pixels.
rank – What pixel value to pick. Use 0 for a min filter, size * size / 2 for a median filter, size * size - 1 for a max filter, etc.
class PIL.ImageFilter.MedianFilter(size=3)
Create a median filter. Picks the median pixel value in a window with the given size.
size – The kernel size, in pixels.
class PIL.ImageFilter.MinFilter(size=3)
Create a min filter. Picks the lowest pixel value in a window with the given size.
size – The kernel size, in pixels.
class PIL.ImageFilter.MaxFilter(size=3)
Create a max filter. Picks the largest pixel value in a window with the given size.
size – The kernel size, in pixels.
class PIL.ImageFilter.ModeFilter(size=3)
Create a mode filter. Picks the most frequent pixel value in a box with the given size. Pixel values that occur only once
if no pixel value occurs more than twice, the original pixel value is preserved.
size – The kernel size, in pixels.
更多详细内容可以参考:
9)图像增强
图像增强也是图像预处理中的一个基本技术,Pillow中的图像增强函数主要在ImageEnhance模块下,通过该模块可以调节图像的颜色、对比度和饱和度和锐化等:
from PIL import ImageEnhance
imgE = Image.open("E:/photoshop/lena.jpg")
imgEH = ImageEnhance.Contrast(imgE)
imgEH.enhance(1.3).show("30% more contrast")
from PIL import ImageEnhance&imgE = Image.open("E:/photoshop/lena.jpg")imgEH = ImageEnhance.Contrast(imgE)imgEH.enhance(1.3).show("30% more contrast")
图像增强:
class PIL.ImageEnhance.Color(image)
Adjust image color balance.
This class can be used to adjust the colour balance of an image, in a manner similar to the controls on a colour TV set. An enhancement factor of 0.0 gives a black and white image. A factor of 1.0 gives the original image.
class PIL.ImageEnhance.Contrast(image)
Adjust image contrast.
This class can be used to control the contrast of an image, similar to the contrast control on a TV set. An enhancement factor of 0.0 gives a solid grey image. A factor of 1.0 gives the original image.
class PIL.ImageEnhance.Brightness(image)
Adjust image brightness.
This class can be used to control the brighntess of an image. An enhancement factor of 0.0 gives a black image. A factor of 1.0 gives the original image.
class PIL.ImageEnhance.Sharpness(image)
Adjust image sharpness.
This class can be used to adjust the sharpness of an image. An enhancement factor of 0.0 gives a blurred image, a factor of 1.0 gives the original image, and a factor of 2.0 gives a sharpened image.
图像增强的详细内容可以参考:
除了以上介绍的内容外,Pillow还有很多强大的功能:
PIL.Image.alpha_composite(im1, im2)
PIL.Image.blend(im1, im2, alpha)
PIL.Image.composite(image1, image2, mask)
PIL.Image.eval(image, *args)
PIL.Image.fromarray(obj, mode=None)
PIL.Image.frombuffer(mode, size, data, decoder_name=’raw’, *args)
想了解更多,请参考:和
参考资料:
可能感兴趣的话题
o 256 回复
关于 Python 频道
Python频道分享 Python 开发技术、相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线

我要回帖

更多关于 python 图像处理入门 的文章

 

随机推荐