本文介绍图像处理中的一些基本概念,包括图像加强、图像增广、边缘提取等。本文的代码使用OpenCV的python接口,及Numpy。python
基础操做
随机生成像素
rows=200 cols=300 num=2000 #随机像素点的个数 img=np.zeros((rows,cols,3),np.unit8) pos1=np.random.randint(200,size=(num,1)) #行位置随机数组 pos2=np.random.randint(300,size=(num,1)) #列 #随机位置处设置像素点值 for i in range(num): img[pos1[i],pos2[i],[0]]=np.random.randint(0,255) img[pos1[i],pos2[i],[1]]=np.random.randint(0,255) img[pos1[i],pos2[i],[2]]=np.random.randint(0,255) 若是在OpenCV中处理图像,是BGR的顺序。
调节图像亮度
将每一个像素的RGB值变小则亮度调小,变暗;将值变大则变亮。算法
日落效果
将蓝色与绿色值设为原来的70%数组
负片
反色,将像素的三色值设为(255-原值)dom
水印
cv2.putText(img,"xxxtext",(pos_x,pos_y),cv2.FONT_HERSHEY_PLAIN,2.0,(0,0,0),thickness=2)
机器学习
旋转、平铺、镜像
旋转必定的角度比较麻烦一些,平铺、镜像简单ide
图像融合
将两个图像对应元素相加取平均。函数
减均值
从图像中减去均值有助于在不一样光照条件下对图像进行归一化。通常代码为: image = image - image.mean()
布局
二值化
将图像进行二值化能够呈现明显的黑白视觉效果。比较简单的方法是卡阈值:对于每个像素,大于阈值的设为1,其它设为0,将图像转换为二值图像,能够用于选择感兴趣的区域。其中一种选择阈值的方法叫Otsu,须要先把图像转换为灰度图。此外还有Ridley-Calvard方法等。 OpenCV的threshold方法:retval,dst = cv2.threshold(src,thresh,maxval,type)
用来简单地卡阈值,adaptiveThreshold
方法能够自适应二值化,参数blockSize决定局部阈值的block大小,其值较小时能够提取边缘。学习
灰度化
灰度图像是一种具备从黑到白256级灰度色阶或等级的单色图像,每一个像素均用8位数据表示。图像只有灰度等级,没有颜色的变化。值越大,显示效果越亮。 两种方式:测试
- 求出每一个像素点的RGB三个份量的平均值,而后将此值赋予三个份量。(结果图还是24bit深度)
- 根据RGB与YUV颜色空间的变化关系,创建亮度Y与RGB三个颜色通道的对应关系:Y=0.3R+0.59G+0.11B,以这个亮度值表达图像的灰度值。(8bit深度)
img2 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
灰度变换与图像加强
灰度变换
将每个像素的灰度值按照必定的数学变换公式转换成一个新的灰度值,以此来加强图像,扩展图像的对比度,使图像变清晰,使其特征更加突出
变换方式
- 对数变换(低亮度区更清晰)
- 分段线性变换(经过压缩高亮度区,扩展低亮度区使图像的对比度增长)
- 指数变换(突出显示高亮度区,使亮的更亮)
- 直方图均衡化 经过统计灰度值的直方图数据,再转成累加几率函数,再映射到原来值的范围以内。这样使得本来相近的灰度值差值变大,像素间的对比度增大。这样增长了全局对比度,尤为使局部的对比更明显。 OpenCV中有
cv2.equalizeHist(srcImg) -> dstImg
可直接使用。
彩色图像直方图均衡化
OpenCV 能够对灰度图进行equalizeHist(graySrc, dst)
; 咱们也能够对彩色图像作直方图均衡化.
- 方法一. 对RGB三通道各自均衡化后,再组合输出结果.
- 方法二. 将RGB图像转化为HSI/YUV/YCbCr等颜色空间后,对亮度通道进行均衡化运算后再转回RGB空间.
C++ 代码实现。 方法一:各个通道分别均衡化:
vector<Mat> channels; split(inputImage, channels); Mat B,G,R; equalizeHist( channels[0], B ); equalizeHist( channels[1], G ); equalizeHist( channels[2], R ); vector<Mat> combined; combined.push_back(B); combined.push_back(G); combined.push_back(R); Mat result; merge(combined, result);
方法二: 亮度均衡化
Mat ycrcb; cvtColor(inputImage, ycrcb, COLOR_BGR2YCrCb); vector<Mat> channels; split(ycrcb, channels); equalizeHist(channels[0], channels[0]); Mat result; merge(channels,ycrcb); cvtColor(ycrcb, result, COLOR_YCrCb2BGR);
RGB各通道均衡化后图像颜色有失真状况,而亮度通道均衡化结果不会.均衡化是针对亮度的而不是针对颜色的.推荐使用YCbCr颜色空间对亮度进行均衡化,由于该颜色空间是为数码图片设计的.
图像噪声
图像加噪(椒盐噪声)
修改若干像素点的值为某一像素值。生成单个随机位置的代码:
xi=int(np.random.uniform(0,img.shape[1])) xj=int(np.random.uniform(0,img.shape[0])) if img.ndim == 2: #gray dim img[xj,xi]=255 elif img.ndim == 3: img[xj,xi,:]=[B,G,R]
图像加噪的目的
:为了试验图像识别的效果,测试机器学习算法的能力。 pepper代指几乎为黑色的值,如30;salt代指几乎为白色的值,如170.
图像滤波与去燥
均一化块
核函数 K = $$\frac{1}{9} \left[ \begin{matrix} 1 & 1 & 1 \ 1 & 1 & 1 \ 1 & 1 & 1 \end{matrix} \right] \tag{1} $$ $$\frac{1}{10} \left[ \begin{matrix} 1 & 1 & 1 \ 1 & 2 & 1 \ 1 & 1 & 1 \end{matrix} \right] \tag{2} $$ $$\frac{1}{16} \left[ \begin{matrix} 1 & 2 & 1 \ 2 & 4 & 2 \ 1 & 2 & 1 \end{matrix} \right] \tag{3} $$ OpenCV 的 blur
函数能够进行归一化块滤波操做。
领域平均法
核: 半径为1:$$\frac{1}{4} \left[ \begin{matrix} 0 & 1 & 0 \ 1 & 0 & 1 \ 0 & 1 & 0 \end{matrix} \right] \tag{1} $$ 半径为2:$$\frac{1}{8} \left[ \begin{matrix} 1 & 1 & 1 \ 1 & 0 & 1 \ 1 & 1 & 1 \end{matrix} \right] \tag{2} $$
中值滤波
与领域平均法的区别为计算的是中值而不是平均值。
高斯滤波(高斯模糊)
对整幅图像中的每一个像素计算领域内像素的加权平均值,权值即卷积核(或称模板)。 OpenCV 有 GaussianBlur
函数。滤波器大小(标准差)越大,图片结果越模糊。经过模糊化,把和整体布局无关的细节都去掉了。经常使用于降噪,能够对后续的处理有所帮助。
聚焦中心:使用高斯模糊进行模糊化,再用高斯函数赋予中心区域一个高权重。能够图像边缘较为柔和,焦点集中于中央区域。
双边滤波
cv2.bilateralFilter
是一种非线性的滤波方法,是结合图像的空间邻近度和像素值类似度的一种折中处理方法,同时考虑空域信息和灰度类似性,达到保边去噪的目的。
卷积滤波
对每个像素,以其为中心的卷积核大小的矩阵与卷积核对应元素相乘再累加求和,和上边的方法很类似。
gabor 滤波 ^gabor
gabor filter是经典的带通滤波器之一,能够用来提取图像边缘.(深度学习的相关论文有些以本身的模型可以学习出相似 gabor filter 的参数为荣). 在图像处理领域,以Dennis Gabor命名的Gabor滤波器,是一种用于纹理分析的线性滤波器,即它主要分析的是,图像在某一特定区域的特定方向上是否有特定的频率内容。当代许多视觉科学家认为,Gabor滤波器的频率和方向的表达与人类的视觉系统很类似,尽管并无实验性证据和函数原理能证实这一观点。研究发现,Gabor滤波器特别适合于纹理表示和辨别。在空间域中,2D Gabor滤波器是由正弦平面波调制的高斯核函数。
滤波与边缘检测
- Laplacian边缘检测使用了Sobel算子
- sobel非线性滤波,采用梯度的模的计算方式提取边缘,锐化图像。(能够将颜色反转,255-原值,以便更好地看出边缘效果。)
- gabor 滤波能够用来提取图像边缘。
图像边缘勾勒:将当前像素与邻接的下部和右部的像素进行比较,若是类似,则将当前像素设置为黑色,不然设置为白色。(也能够为中间值设置一些中间色)。
图像导数
图像中的强度变化状况一般能够做为重要的信息,强度的变化能够用灰度图像I(对于彩色图像,一般对每一个颜色通道分别计算导数)的x和y方向导数$I_x,I_y$进行描述。 梯度向量为$\nabla I=[I_x,I_y]^T$。 梯度有两个重要的属性, 一是梯度大小,描述了图像强度变化的强弱: $$|\nabla I|=\sqrt{I_x^2+I_y^2}$$ 一是梯度的角度,描述了图像在每一个像素点上强度变化最大的方向。 $$\alpha=\arctan2(I_y,I_x)$$
近似计算
图像导数大多能够经过卷积来简单地计算离散近似值: $$I_x=ID_x$$ $$I_y=ID_y$$ 一般选择Prewitt滤波器: $$ D_x= \begin{bmatrix} -1 & 0 & 1 \ -1 & 0 & 1 \ -1 & 0 & 1 \ \end{bmatrix} $$ $$ D_y= \begin{bmatrix} -1 & -1 & -1 \ 0 & 0 & 0 \ 1 & 1 & 1 \ \end{bmatrix} $$ 或Sobel滤波器: $$ D_x= \begin{bmatrix} -1 & 0 & 1 \ -2 & 0 & 2 \ -1 & 0 & 1 \ \end{bmatrix} $$ $$ D_y= \begin{bmatrix} -1 & -2 & -1 \ 0 & 0 & 0 \ 1 & 2 & 1 \ \end{bmatrix} $$ 这些导数滤波器可使用scipy.ndimage.filters
模块的标准卷积操做来简单实现。
上述方法的缺陷
滤波器的尺度须要随着图像分辨率的变化而变化。 为了在图像噪声方面更稳健,以及在任意尺度上计算导数,咱们可使用高斯导数滤波器。filters.gaussian_filter()
模式识别
因为历史的缘由,图像分类又叫作模式识别。 模式识别一般包括分解、特征提取、分类几个过程。分解的内容多是图像、数据,这个分解过程实现自动化是较难的,分解后造成分区、有限的内容子集。特征提取分析不一样类的不一样的特征,须要对分解后的内容进行各类数学分析。分类基于特征分析来进行。
模式识别难点
- 视角不一样viewpoint variation
- 尺寸大小不一scale variation
- 变形deformation
- 光影等干扰occlusion/illumination conditions
- 背景干扰background clutter
- 同类物体的差别intra-class variation
图像匹配
判断图片A是不是图片B的子图。
- 差分矩阵 差分矩阵 = 图像A矩阵 - 图像B矩阵 若差分矩阵每一个元素的和或矩阵均值小于某一阈值,则认为匹配。
- 欧式距离 对于强噪声环境下以及旋转的图像进行匹配时,欧式距离匹配方法相对于查分矩阵会有更好的效果。
def getEuclideanDist(x,y): ax=np.array(x) ay=np.array(y) return np.sqrt(np.sum((ax-ay)*(ax-ay)))
图像增广
图像数据扩增(data augmentation):
- 水平翻转(Horizontal flipping) (垂直翻转根据视角是否有上下颠倒的需求而定)
- 随机裁剪(Random cropping)
- 随机放缩(Random scaling)
- 颜色抖动(Color jittering)
- 随机平移(Random translation)
- 随机剪切(Random shearing)
较经常使用的有水平翻转, 随机裁剪和颜色抖动. 而且能够组合多种方式. 能够改变saturation 和 value (HSV 颜色空间的S和V组件) 的值等方式.
图像聚类
聚类能够用于识别、划分图像数据集,组织与导航。此后能够对聚类后的图像进行类似性可视化。