AI: 图像处理基础(Image Processing Basics)
注:基本部分来自MPP,参加MPP的学习笔记,以方便学习理解和记忆。
一,灰度处理(Grayscale)
计算机在处理图像时,图像是一串0-255数字组成三维数组。如下图:
这是一幅AI全家福照片,作为一个数字图像,它实际可以用一个数组表示像素强度在0到255之间的数字来表示。
。如图右下侧的三维数字来表示,不同的维度分别代表红色,绿色和蓝色。
如果把图片的颜色去掉,仅仅使用一个二维数组就可以了。如下图,计算机用一个二维数组来展示这个图像。
灰度处理的方法很多,这里仅仅介绍使用Python的方法,这部分我没有使用课件的代码;示例1
#引入包 import matplotlib.pyplot as plt %matplotlib inline import numpy as np #读取文件 zhima=plt.imread('芝麻.jpg') plt.imshow(zhima) #转变需要的类型,并且产生噪声,显示最后的图片 zhima_noisy=zhima.copy().astype(float) zhima_noisy+=zhima_noisy.std()*0.3*np.random.standard_normal(zhima_noisy.shape) plt.imshow(zhima_noisy) #查看形状 zhima.shape #输出结果为:(662, 1000, 3) 平均值法 #聚合操作后就减少了一个维度了 zhima_mean=zhima.mean(axis=2) zhima_mean.shape #输出结果为:(662, 1000) plt.imshow(zhima_mean,cmap='gray') #最大值法 zhima_max=zhima.max(axis=-1) zhima_max.shape plt.imshow(zhima_max,cmap='gray') RGB三原色法 gravity= np.array([0.299,0.587,0.114]) #red*0.299+green*0.587+blue*0.114 #矩阵乘法 zhima_gravity=np.dot(zhima,gravity) zhima_gravity.shape plt.imshow(zhima_gravity,cmap='gray')
示例2
import matplotlib.pyplot as plt from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets mnist = read_data_sets('MNIST_data', one_hot=False) x, y = mnist.test.next_batch(1) x = x.reshape([28, 28]) fig = plt.figure() # Method1 ax1 = fig.add_subplot(221) ax1.imshow(x, cmap=plt.cm.gray) # Method2: 反转色 ax2 = fig.add_subplot(222) ax2.imshow(x, cmap=plt.cm.gray_r) # r表示reverse # Method3(等价于Method1) ax3 = fig.add_subplot(223) ax3.imshow(x, cmap='gray') # Method4(等价于Method2) ax4 = fig.add_subplot(224) ax4.imshow(x, cmap='gray_r') plt.show() plt.savefig("gray.png")
图像的灰度直方图能够很直观的展示图像中灰度级的整体分布情况,对图像的后续处理有很好的指导作用。
二,均衡处理(Equalization)
均衡处理之前先来对比2个图片,左侧为均衡处理之前,右侧为均衡处理之后。
为什么要做图像的均衡处理:
假如图像的灰度分布不均匀,其灰度分布集中在较窄的范围内,使图像的细节不够清晰,对比度较低。通常采用直方图均衡化及直方图规定化两种变换,使图像的灰度范围拉开或使灰度均匀分布,从而增大反差,使图像细节清晰,以达到增强的目的。
直方图均衡化,对图像进行非线性拉伸,重新分配图像的灰度值,使一定范围内图像的灰度值大致相等。这样,原来直方图中间的峰值部分对比度得到增强,而两侧的谷底部分对比度降低,输出图像的直方图是一个较为平坦的直方图。
图像均衡处理示例代码1
******************************************************************************************** 均衡原图-(直方图基本操作) *******************************************************************************************/ void InitMappingTable(void * arry,int size,int Data_type){ if(Data_type==TABLE_INT) for(int i=0;i<size;i++) ((int*)arry)[i]=0; else if(Data_type==TABLE_CHAR) for(int i=0;i<size;i++) ((char*)arry)[i]=0; else if(Data_type==TABLE_DOUBLE) for(int i=0;i<size;i++) ((double*)arry)[i]=0; } void InitHistogram(int *hist){ for(int i=0;i<GRAY_LEVEL;i++) hist[i]=0; } void setHistogram(double *src,int *hist,int width,int height){ InitHistogram(hist); for(int j=0;j<height;j++) for(int i=0;i<width;i++){ int tempv=src[j*width+i]; hist[tempv]++; } } int findHistogramMax(int *hist){ for(int i=GRAY_LEVEL-1;i>=0;i--){ if(hist[i]!=0) return i; } return -1; } int findHistogramMin(int *hist){ for(int i=0;i<GRAY_LEVEL;i++){ if(hist[i]!=0) return i; } return -1; } void fillMaptable(double * map){ for(int i=1;i<GRAY_LEVEL;i++){ if(map[i]==0) map[i]=map[i-1]; } } /******************************************************************************************** 直方图均衡 *******************************************************************************************/ //均衡直方图,将原图直方图,经过公式得到目标直方图 void EqualizationHist(int *src_hist,double *dst_map){ int temphist[GRAY_LEVEL]; InitHistogram(temphist); int max=findHistogramMax(src_hist); int min=findHistogramMin(src_hist); temphist[min]=src_hist[min]; for(int i=min+1;i<=max;i++) temphist[i]=temphist[i-1]+src_hist[i]; for(int i=max;i>=min;i--)//感谢pymess同学指正,之前的有问题 temphist[i]-=temphist[min]; int total=temphist[max]; for(int i=min;i<=max;i++){ dst_map[i]=((double)GRAY_LEVEL-1.0)*temphist[i]/total; } } //直方图均很,用输入图像得到输出图像 void HistogramEqualization(double *src,double *dst,int width,int height){ int hist[GRAY_LEVEL]; setHistogram(src, hist, width, height); double GrayMappingTable[GRAY_LEVEL]; InitMappingTable(GrayMappingTable,GRAY_LEVEL,TABLE_DOUBLE); EqualizationHist(hist, GrayMappingTable); for(int i=0;i<width;i++) for(int j=0;j<height;j++) dst[j*width+i]=GrayMappingTable[(int)src[j*width+i]]; }
图像均衡处理示例代码2 使用了一个函数来做。
void equalization_self(const Mat &src, Mat &dst) { Histogram1D hist1D; MatND hist = hist1D.getHistogram(src); hist /= (src.rows * src.cols); // 对得到的灰度直方图进行归一化 float cdf[256] = { 0 }; // 灰度的累积概率 Mat lut(1, 256, CV_8U); // 灰度变换的查找表 for (int i = 0; i < 256; i++) { // 计算灰度级的累积概率 if (i == 0) cdf[i] = hist.at<float>(i); else cdf[i] = cdf[i - 1] + hist.at<float>(i); lut.at<uchar>(i) = static_cast<uchar>(255 * cdf[i]); // 创建灰度的查找表 } LUT(src, lut, dst); // 应用查找表,进行灰度变化,得到均衡化后的图像 }直方图的均衡化的是将一幅图像的直方图变平,使各个灰度级的趋于均匀分布,这样能够很好的增强图像对比度。直方图均衡化是一种自动化的变换,仅需要输入图像,就能够确定图像的变换函数。但是直方图的均衡化操作也有一定的确定,在均衡化的过程中对图像中的数据不加选择,这样有可能会增强图像的背景;变换后图像的灰度级减少,有可能造成某些细节的消失;会压缩图像直方图中的高峰,造成处理后图像对比度的不自然等。
三,过滤器(Filters)
图像一般会有噪点,这些噪点模糊了细节,所以必须要做降噪处理,例如Filters。现在看如下图。
处理前:
降噪处理后一次,如下图,看上去这个图像比较模糊,要调整数字,重新处理;
第二次降噪处理,蒙版数值减少10个值,如下图。看上去清楚多了。
由于成像系统、传输介质和记录设备等的不完善,数字图像在其形成、传输记录过程中往往会受到多种噪声的污染。另外,在图像处理的某些环节当输入的像对象并不如预想时也会在结果图像中引入噪声。要构造一种有效抑制噪声的滤波器必须考虑两个基本问题:能有效地去除目标和背景中的噪声;同时,能很好地保护图像目标的形状、大小及特定的几何和拓扑结构特征。
from PIL import Image from PIL import ImageFilter def image_filters_test(): im = Image.open("lenna.jpg") #预定义的图像增强滤波器 im_blur = im.filter(ImageFilter.BLUR) im_contour = im.filter(ImageFilter.CONTOUR) im_min = im.filter(ImageFilter.MinFilter(3)) im.show() im_blur.show() im_contour.show() im_min.show() return
示例代码二
模糊滤波 from PIL import Image, ImageFilter im = Image.open(r"C:\Users\admin\Desktop\Penguins.jpg") bluF = im.filter(ImageFilter.BLUR) bluF.show() 轮廓滤波 from PIL import Image, ImageFilter im = Image.open(r"C:\Users\admin\Desktop\Penguins.jpg") conF = im.filter(ImageFilter.CONTOUR) conF.show() 细节滤波 from PIL import Image, ImageFilter im = Image.open(r"C:\Users\admin\Desktop\Penguins.jpg") detF = im.filter(ImageFilter.DETAIL) detF.show() 最小值滤波 from PIL import Image, ImageFilter im = Image.open(r"C:\Users\admin\Desktop\Penguins.jpg") minF = im.filter(ImageFilter.MinFilter(5)) 中值滤波 from PIL import Image, ImageFilter im = Image.open(r"C:\Users\admin\Desktop\Penguins.jpg") medF = im.filter(ImageFilter.MedianFilter(5)) medF.show() 最大值滤波 from PIL import Image, ImageFilter im = Image.open(r"C:\Users\admin\Desktop\Penguins.jpg") maxF = im.filter(ImageFilter.MaxFilter(5)) maxF.show()