图像处理基础

为了响应国际庄女菩萨的号召,首先介绍下图像入门的基础名词:

  • 像素:像素是分辨率的单位,像素是构成位图图像最基本的单元,每个像素都有自己的颜色。

  • 分辨率:单位英寸内的像素点数,单位是PPI(Pixeks Per Lnch),表示每英寸对角线上所拥有的像素数目。

  • RGB:指的是图片中的光学三原色(red、green、blue),与日常生活中的光学三原色是有区别。

  • 灰度:表示图像像素明暗程度的值,就是黑白图像中的颜色深度,范围是在0-255,白色为255,黑色为0.

  • 通道:把图像分解成一个或多个颜色分成:
    1、单通道:一个像素点只需要一个数值表示,只能表示灰度。(二值图&灰度图)。
    2、三通道:RGB模式,把图像分为红绿蓝三个通道,可以表示彩色,也可以自定义通道颜色,全0为黑色。
    3、四通道:RGBA模式,在RGB的基础上加了alpha通道,表示透明度,alpha=0表示全透明

  • 对比度:指不同颜色之间的差别。对比度 = 最大灰度值/最小灰度值。

  • 频率:灰度值变化剧烈程度的指标,是灰度在平面空间上的梯度。

  • 为什么很多图像识别将彩色图像灰度化?
    目的是为了简化矩阵,提高运算速度。彩色图片中的信息含量过大,进行图像识别时灰度图像的信息足够。

下面开始对图像的基本操作进行沉浸式学习。 がんばれ、兄弟姉妹たち!!

图像处理基础

  • 加载图像
  • 保存图像
  • 调整图像大小
  • 裁剪图像
  • 平滑处理图像
  • 图像锐化
  • 提升对比度
  • 颜色分离
  • 图像二值化
  • 移除背景
  • 边缘检测
  • 角点检测
  • 为机器学习创建特征
  • 将颜色平均值编码成特征
  • 将色彩直方图编码成特征

使用的python工具包有openCV、Numpy、Matplotlib,根据自己的python版本安装使用。
推荐百度的镜像,下载速度很快:-i https://mirror.baidu.com/pypi/simple

加载图像

cv2.IMREAD_GRAYSCALE,指的是灰度模式读取一张图片,实际取值为0
plt.axis(“off”),指的是关闭坐标轴

#把图像导入成灰度图
image = cv2.imread('image/plan.png',cv2.IMREAD_GRAYSCALE)
#如果想查看图片可以使用
plt.imshow(image,cmap='gray'),plt.axis("off")
plt.show()

保存图像

image = cv2.imread('image/plan.png',cv2.IMREAD_GRAYSCALE)
cv2.imwrite('image/plan_save.png',image)

调整图像大小

因为被用作特征的图像必须有相同的大小(像素数),其次是被标准化的处理图像会带来一些像素上的损失,其中包含的信息也会随之减少,优点是,成百上千张图片在计算时可以大大较少内存的使用量。

#以灰度图格式导入图像
image = cv2.imread('image/plan_256*256.png',cv2.IMREAD_GRAYSCALE)
#将图片尺寸调整为50*50像素
image_50_50 = cv2.resize(image,(50,50))
#查看图片
plt.imshow(image_50_50,cmap='gray'),plt.axis("off")
plt.show()

裁剪图像

选择要保留的行和列,裁剪出感兴趣的区域。 比如说小区的门禁,把脸裁出来。

#以灰度图格式导入图像
image = cv2.imread('image/plan_256*256.png',cv2.IMREAD_GRAYSCALE)
#选择所有行和前128列
image_cropped = image[:,:128]
#查看图片
plt.imshow(image_cropped,cmap='gray'),plt.axis("off")
plt.show()

平滑处理图像

平滑处理是指将每个像素的值变换为其相邻像素的平均值。相邻像素和执行的操作在数学上表示为一个核,这个核的大小决定了平滑程度,核越大,产生的图像越平滑。本例使用的是一个5*5的核,感兴趣可以试一下不同的是什么效果。

#以灰度图格式导入图像
image = cv2.imread('image/plan_256*256.png',cv2.IMREAD_GRAYSCALE)
#平滑处理图像
image_blurry = cv2.blur(image,(5,5))
#查看图片
plt.imshow(image_blurry,cmap='gray'),plt.axis("off")
plt.show()

图像锐化

锐化与平滑的原理相似,在平滑处理中,使用核来平均处理相邻像素的值,在锐化时,使用的是能突出显示像素自身的核,锐化可以使图像的边缘更加突出。

#以灰度图格式导入图像
image = cv2.imread('image/plan_256*256.png',cv2.IMREAD_GRAYSCALE)
#创建核
kernel = np.array([[0,-1,0],
                   [-1,-5,1],
                   [0,-3,-1]])
#锐化图像
image_sharp = cv2.filter2D(image,-1,kernel)
#查看图片
plt.imshow(image_blurry,cmap='gray'),plt.axis("off")
plt.show()

提升对比度

通过转换图像,使图像像素强度的分布范围更广,经过直方均衡后的图片往往看起来不真实,但要明白,图像只是底层数据的可视化表示,如果直方图均衡能够使感兴趣的对象与其他对象或背景区分明显,那便是对于图像预处理流水线是一个非常有价值的补充。

#加载图像
image = cv2.imread('image/plan_256*256.png',cv2.IMREAD_GRAYSCALE)
#增强图像
image_enhanced = cv2.equalizeHist(image)
#查看图片
plt.imshow(image_enhanced,cmap='gray'),plt.axis("off")
plt.show()

颜色分离

首先,将图像转换为HSV格式(色调、饱和度、亮度)。其次定义分离的值,然后为图像创建一个掩膜,即只保留掩膜的白色区域,最后使用bitwise_and方法将掩膜应用于图像,并将图像转换成所需的格式。

#颜色分离
image_bar = cv2.imread('image/plan_256*256.png')
#将RGB格式转换为HSV格式
image_hsv = cv2.cvtColor(image_bar,cv2.COLOR_BGR2HLS)
#定义HSV格式中蓝色分量的区间
lower_blue = np.array([50,100,50])
upper_blue = np.array([130,255,255])
#创建掩模
mask = cv2.inRange(image_hsv,lower_blue,upper_blue)
#应用掩膜
image_bgr_masked = cv2.bitwise_and(image_bar,image_bar,mask=mask)
#从BGR格式转换成RGB格式
image_rgb = cv2.cvtColor(image_bgr_masked,cv2.COLOR_BGR2RGB)
#查看图片
plt.imshow(image_rgb),plt.axis("off")
plt.show()

图像二值化

图像二值化是指对图像进行阈值处理(thresholding),即将强度大于某个阈值的像素设置为白色并将小于该值的像素设置为黑色的过程。

#加载图像
image_grey = cv2.imread('image/plan_256*256.png',cv2.IMREAD_GRAYSCALE)
#应用自适应阀值处理
max_output_value = 255
neighborhood_size = 99
subtract_from_mean = 10
image_binarized = cv2.adaptiveThreshold(image_grey, #图像
                                        max_output_value, #像素的最大强度
                                        cv2.ADAPTIVE_THRESH_GAUSSIAN_C, #将像素阈值设置为相邻像素强度的加权和,期权重由高斯窗口确定。
                                        cv2.THRESH_BINARY, #相邻像素的平均值作为阈值
                                        neighborhood_size,#块大小(用于确定像素阈值的邻域大小)
                                        subtract_from_mean #手动调整阈值的常数(从计算出的阈值减去该常数))
#查看图片
plt.imshow(image_rgb),plt.axis("off")
plt.show()

移除背景

移除背景首先是在包含前景的区域中画一个矩形。GrabCut认为矩形之外的都是背景,并使用这些信息找出矩形内可能的背景,算法背后生成一个掩膜,他可以标出确定为背景的区域,可能为前景的区域,然后用这个掩膜生成一个新的掩膜,新掩膜会将黑色和灰色区域合并。将第二个掩膜应用到图像上,得到最终的图像。
目前实践得到结果仍会残留部分背景区域。并不是最佳选择,学习用

#加载图像,并将其转换为RGB格式
image_bar = cv2.imread('image/plan_256*256.png')
image_rgb = cv2.cvtColor(image_bar,cv2.COLOR_BGR2RGB)
#矩阵的值,左上角的x坐标,左上角的Y坐标,宽,高
rectangle = (0,56,256,150)
#创建初始掩膜
mask = np.zeros(image_rgb.shape[:2],np.uint8)
#创建grabcut函数需要的临时数组
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)

#执行grabcut函数
cv2.grabCut(image_rgb, #图像
			mask , #掩膜
            rectangle, #矩形
            bgdModel, #背景的临时数组
            fgdModel, #前景的临时数组
            5, #迭代次数
            cv2.GC_INIT_WITH_RECT) #使用定义的矩形初始化
#创建一个掩膜。将确定或可能是背景的部分设置为0,其余部分设置为1
mask_2 = np.where((mask==2) | (mask==0),0,1).astype('uint8')
#将图像与掩码相乘除以背景
image_rgb_nobg = image_rgb * mask_2[:,:,np.newaxis]
#查看图片
plt.imshow(image_rgb_nobg),plt.axis("off")
plt.show()

边缘检测

边缘检测可以帮助我们去除低信息含量的区域,并将信息含量最高的区域从原始图像中分离出来。
此解决方案使用的Canny边缘检测器,需要两个参数来表示梯度的低阈值和高阈值。处于低阈值和高阈值之间的潜在边缘像素认为是弱像素,高于阈值的则被认定为强像素。在决绝方案中将两个阈值分别设置为低于和高于像素强度的一个标准差值,对于整个图像集运行之前,先用一小部分试错,手动调整阈值。然后就去接杯水,上走廊上转转,期待好的结果吧!

#加载图像
image_gray = cv2.imread('image/plan_256*256.png',cv2.IMREAD_GRAYSCALE)
#计算像素强度中的中位数
median_intensity = np.median(image_gray)
#设置阈值
lower_threshold = int(max(0,(1.0 - 0.33) * median_intensity))
upper_threshold = int(max(255,(1.0 - 0.33) * median_intensity))
#应用Canny检测器
image_canny = cv2.Canny(image_gray,lower_threshold,upper_threshold)
#显示图像
plt.imshow(image_rgb_nobg),plt.axis("off")
plt.show()

角点检测

Harris检测器是检测两条边缘线条的交叉点常用方法。
Harris检测器会寻找一个窗口(邻域),这个窗口微小的移动(也可以叫晃动窗口)会引发窗口内的像素值大幅变化,然后使用阈值筛选出最可能的点。

#以灰度图模式加载图像
image_bar = cv2.imread('image/plan_256*256.png')
image_gray = cv2.cvtColor(image_bar,cv2.COLOR_BGR2GRAY)
image_gray = np.float32(image_gray)

#设置角点检测器的参数
block_size = 2
aperture = 29
free_parameter = 0.04
#检测角点
detector_responses = cv2.cornerHarris(image_gray,
                                      block_size,#角点检测中的窗口尺寸
                                      aperture,#代表soble算子尺寸
                                      free_parameter)#用于控制对角点检测的严格程度,这个值越大,可以识别的觉点越平滑
#放大角点标志
detector_responses = cv2.dilate(detector_responses,None)
#只保留大于阈值的检测结果,并把它们标记成白色
threshold = 0.02
image_bgr = [detector_responses >
             threshold *
             detector_responses.max()] = [255,255,255]
#转换成灰度图
image_gray = cv2.cvtColor(image_bar,cv2.COLOR_BGR2GRAY)
#显示图像
plt.imshow(image_rgb_nobg),plt.axis("off")
plt.show()

为机器学习创建特征

图像是像素点的网格来表示的。如果是灰度图,则每个像素用一个值表示(即像素的强度,白色为255,黑色为0)。

#加载图像
image = cv2.imread('image/plan_256*256.png',cv2.IMREAD_GRAYSCALE)
#将图像尺寸转换成10*10
image_10_10 = cv2.resize(image,(10,10))
#将图像数据转换成一维响亮
image_10_10.flatten()

将颜色平均值编码成特征

输出三个特征的值,分别来自图像的个自颜色通道,根据颜色对图像进行分类。

#加载图像
image_bgr = cv2.imread('image/plan_256*256.png',cv2.IMREAD_COLOR)
#计算每个通道的平均值
channels = cv2.mean(image_bar)

#交换红色和蓝色的通道,将图像从BGR格式转换成RGB格式
observation = np.array([channels[2],channels[1],channels[0]])
#显示图像
plt.imshow(observation),plt.axis("off")
plt.show()

将色彩直方图编码成特征

在RGB色彩模型中,每种颜色是由三个通道的值组合而成的,每个通道可以取0-255之间的整数。可以提取出个个通道所占的像素个数,输出特征从而进行机器学习。

#加载图像
image_bgr = cv2.imread('image/plan_256*256.png',cv2.IMREAD_COLOR)
#将图像转换成RGB格式
image_rgb = cv2.cvtColor(image_bar,cv2.COLOR_BGR2RGB)
#创建一个特征列表
features = []
#为每一个颜色通道计算直方图
colors = ['r','g','b']
#为每一个通道计算直方图并把它加入特征列表中
for i, channel in enumerate(colors):
    histogram = cv2.calcHist([image_rgb],
                             [i],
                             None,
                             [256],
                             [0,256])
    features.extend(histogram)

#将样本的特征值展开成一维数组
observation = np.array(features).flatten()

写的比较片面很多技术都是很久之前的,但贵在基础,入门比较容易建立信心,有不足的地方欢迎批评指正,祝我们假以时日都能找到自己喜欢的方向。
最后十分感谢Chris Albo大神的书籍给我提供了创作的思路与参考,以及女菩萨对我的谆谆不倦的支持(催更)与鼓励(每天都问)

下班下班~

你可能感兴趣的:(CV天天见,python,图像处理)