使用Numpy和Opencv完成图像的基本数据分析

对于深度学习而言,很多任务都是与数字图形处理打交道。这类任务的数据集一般是由很多张图像构成,有时候,当原始图像不能直接送入模型中时,需要对其进行一定的预处理操作,这时候就不得不向大家介绍一个十分有用的软件包OpenCV,用它处理图像起来非常方便,OpenCV是一个基于BSD许可发行的跨平台计算机视觉库,它轻量且高效,是由一系列C函数和少量C++类构成,支持Python、MATLAB等语言接口,内部包含了很多图像处理的相关算法。下面将向大家介绍如何使用NumPy和OpenCV对数字图像进行简单的处理方法:

关于像素的一些知识

在程序世界里,图像输入到计算机中时,与人眼所见的图像的形式不太一样。计算机将图像存储为类似于马赛克的小方块,就像古老的方块马赛克艺术的形式。如果方形块太大,那么就很难制作出光滑的边缘和曲线。使用的方块越小,则越平滑,或者说图像的像素就越少,方块的大小有时候也被称为图像的分辨率。 矢量图像是存储图像的一些不同方法,目的是为了避免与像素相关的问题。但是,即使是矢量图像,最终也会显示为像素级的马赛克。像素一词表示图像元素,描述每个像素的简单方法是使用三种颜色的组合,即红色(Red),绿色(Green),蓝色(Blue),即我们平时所说的RGB图像。 在RGB图像中,每个像素由分别与红色,绿色,蓝色的值相关联的三个8比特数表示。假设使用放大镜观察,如果我们放大图片,就会看到图片是由微小的光点或更加具体的像素组成,更有趣的是,看到的那些小光点实际上是多个微小不同颜色的小光点,且颜色只有红色、绿色和蓝色。 假设现在从远处观察,创建一张图像,可以看到一张图像实际上由像素点值的开关决定(像素值为1表示开,像素值为0表示关),这些开关组合创建了图像,基本上,我们每天在屏幕上看到的图像都是这种。 每张图像都以数字形式的像素组成,像素是构成图片的最小信息单位,通常是圆形或方形,且位于二维网格中。 现在,如果RGB三个值都处于全强度,这意味着其组合值为255,该值表示为白色,如果所有三种颜色都被减弱,或者值设置为0,其值表示为黑色。反过来,三者的不同组合将为我们提供不同特定的像素颜色。由于每个数字都是8比特,因此像素值的取值范围为0-255,从下图可以看到,但R的强度为37.3%,G的强度为45.9%,B的强度为18.8%时,组合成的颜色为深绿(dark green)。

三种颜色的不同组合将产生不同的颜色,由于每个值可以具有256个不同的强度或亮度值,因此总共有1680万(256 x 256 x 256)种不同组合。 图像的基本知识介绍完毕后进入正题,以下内容将包含Numpy非常基本的图像数据分析、还有一些Python数据包,比如imageio,matplotlib等。本系列博客内容结构如下,先介绍前三个部分:

  • 导入图像并观察其属性
  • 拆分图层
  • 灰度化
  • 对像素值使用逻辑运算符
  • 使用逻辑运算符进行掩码
  • 卫星图像数据分析

导入图像

下面加载图像并观察其各种属性。注意,在输入下面代码请确保好已经安装好对应的python数据包。

if__name__=='__main__':
importimageio
importmatplotlib.pyplotasplt
%matplotlibinlinepic=imageio.imread('F:/demo_2.jpg')
plt.figure(figsize=(15,15))plt.imshow(pic)

观察图像的基本属性

print('Type of the image : ',type(pic))
print()
print('Shape of the image : {}'.format(pic.shape))
print('Image Hight {}'.format(pic.shape[0]))
print('Image Width {}'.format(pic.shape[1]))
print('Dimension of Image {}'.format(pic.ndim))

其输出

Type of the image :<class 'imageio.core.util.Image'>

Shape of the image : (562, 960, 3)
Image Hight 562

Image Width 960

Dimension of Image 3

ndarray的形状表明它是一个三维矩阵,输出结果的前两个数字分别表示高度(height)和宽度(width),第三个数字(即3)表示是该图像是三通道彩色图:红色、绿色和蓝色。因此,如果我们计算RGB图像的大小,则总像素大小将是weiheigh x width x 3

print('Image size {}'.format(pic.size))
print('Maximum RGB value in this image {}'.format(pic.max()))
print('Minimum RGB value in this image {}'.format(pic.min()))Image size 1618560

Maximum RGB value in this image 255

Minimum RGB value in this image 0

这些值对于验证而言是很重要的,因为8位颜色强度不能超出0到255范围。 使用图片可以分配变量,此外还可以访问图像的任何特定像素值,并且还可以分别访问每个RGB通道。

pic[100, 50 ]Image([109, 143,  46], dtype=uint8)

在这种情况下:R = 109、G = 143、 B = 46,从这个配置可以看出该像素中有很多绿色,也可以通过三个通道的索引值来从中选择出一个。根据一般规定:

  • 索引0表示红色通道
  • 索引1表示绿色通道
  • 索引2表示蓝色通道 但在OpenCV中,Images并不是按照RGB的顺序规定,而是BGR。 imageio.imread将图像加载为RGB(或RGBA),但OpenCV假定图像为BGR或BGRA(BGR是OpenCVcolour的默认的式)。
print('Value of only R channel {}'.format(pic[ 100, 50, 0]))
print('Value of only G channel {}'.format(pic[ 100, 50, 1]))
print('Value of only B channel {}'.format(pic[ 100, 50, 2]))Value of only R channel 109

Value of only G channel 143

Value of only B channel 46

现在快速查看整个图像中每个通道表示的图像。

plt.title('R channel')plt.ylabel('Height {}'.format(pic.shape[0]))plt.xlabel('Width {}'.format(pic.shape[1]))plt.imshow(pic[ : , : , 0])plt.show()
plt.title('G channel')plt.ylabel('Height {}'.format(pic.shape[0]))plt.xlabel('Width {}'.format(pic.shape[1]))plt.imshow(pic[ : , : , 1])plt.show()
plt.title('B channel')plt.ylabel('Height {}'.format(pic.shape[0]))plt.xlabel('Width {}'.format(pic.shape[1]))plt.imshow(pic[ : , : , 2])plt.show()

下面,也可以更改RGB的数值。例如,将下面行的红色、绿色、,蓝色图层的值全部设置为全强度,即取值为255。

  • R通道:第100行到110行
  • G通道:第200行到210行
  • B通道:行300行到310行 本次测试只在一张图像上进行综合处理,方便我们同时查看每个通道的值对图像的影响。
pic =imageio.imread('F:/demo_2.jpg')
pic[50:150 , : , 0] =255# full intensity to those pixel's R channel

plt.figure( figsize= (10,10))plt.imshow(pic)plt.show()
pic[200:300 , : , 1] =255# full intensity to those pixel's G channel

plt.figure( figsize= (10,10))plt.imshow(pic)plt.show()
pic[350:450 , : , 2] =255# full intensity to those pixel's B channel

plt.figure( figsize= (10,10))plt.imshow(pic)plt.show()

为了更加清楚地对比分析,我们也改变部分列的像素值,这次测试同时更改RGB通道的值。

pic[50:450 , 400:600 , [0,1,2] ] =200plt.figure( figsize= (10,10))plt.imshow(pic)plt.show()

拆分图层

通过以上测试,可以知道,图像的每个像素点都是由三个整数表示。只需要拉出图像阵列的正确切片,就可以将图像分割成单独的颜色分量。

importnumpyasnppic=imageio.imread('F:/demo_2.jpg')fig,ax=plt.subplots(nrows=1,ncols=3,figsize=(15,5))forc,axinzip(range(3),ax):# create zero matrix

split_img=np.zeros(pic.shape,dtype="uint8")# 'dtype' by default: 'numpy.float64' 

# assing each channel split_img[:,:,c]=pic[:,:,c]

# display each channelax.imshow(split_img)

灰度化

黑白图像存储在二维矩阵中,目前存在两种类型的黑白图像:

  • 灰度:灰色阴影的范围:0~255
  • 二进制:像素为黑色或白色:0或255 灰度处理过程,就是将图像从全彩色转换为灰度图。在图像处理工具中,例如:在OpenCV中,在使用很多含住之前,需要将图像进行灰度处理,这样做是因为灰度处理简化了图像,几乎像降噪一样,这是因为灰度图像中的信息比较少。

在python中有两种方法可以将图像转换为灰度。但是,更直接的方法是使用matplotlib包,该包执行的操作是获取原始图像的RGB值后进行加权平均。

Y' = 0.299 R + 0.587 G + 0.114 B
pic=imageio.imread('F:/demo_2.jpg')
gray=lambdargb:np.dot(rgb[...,:3],[0.299,0.587,0.114])
gray=gray(pic)
plt.figure(figsize=(10,10))
plt.imshow(gray,cmap=plt.get_cmap(name='gray'))
plt.show()

而通过GIMP将颜色转换为灰度图像有三种算法来完成任务:

  • 亮度(Lightness)灰度等级计算为 Lightness = ½×(max(R,G,B)+ min(R,G,B))
  • 照明度(Luminosity)灰度级将计算为 Luminosity= 0.21×R + 0.7×G + 0.07×B
  • 平均亮度灰度级将计算为 Average Brightness=(R + G + B)÷3

下面让我们尝试实现一下这三个算法中的一种吧,本文选择Luminosity。

pic=imageio.imread('F:/demo_2.jpg')gray=lambdargb:np.dot(rgb[...,:3],[0.21,0.72,0.07])gray=gray(pic)plt.figure(figsize=(10,10))plt.imshow(gray,cmap=plt.get_cmap(name='gray'))plt.show()print('Type of the image : ',type(gray))print()print('Shape of the image : {}'.format(gray.shape))
print('Image Hight {}'.format(gray.shape[0]))print('Image Width {}'.format(gray.shape[1]))
print('Dimension of Image {}'.format(gray.ndim))
print()
print('Image size {}'.format(gray.size))
print('Maximum RGB value in this image {}'.format(gray.max()))
print('Minimum RGB value in this image {}'.format(gray.min()))
print('Random indexes [X,Y] : {}'.format(gray[100,50]))
Type of the image :<class 'imageio.core.util.Image'> 

Shape of the image : (562,960)
Image Height 562

Image Widht 960

Dimension of Image 2 
Image size 539520

Maximum RGB value in this image 254.9999999997

Minimum RGB value in this image 0.0

Random indexes [X,Y] : 129.07

使用逻辑操作处理像素值

可以使用逻辑运算符创建相同大小的数组。但是,逻辑运算操作并不会创建出任何新的数组,只是将True返回给主机变量(host variable)。例如:假设在RGB图像中过滤掉一些像素值低的像素或像素值高的像素(以及其它任何条件),将RGB转换为灰度图看起来不错,但是我们目前不会对彩色图像进行这样的处理。 首先加载图像,并将其显示在屏幕上:

pic=imageio.imread('F:/demo_1.jpg')
plt.figure(figsize=(10,10))
plt.imshow(pic)
plt.show()

注意图像的路径问题.之后需要考虑转储这个显示的图像。假设对于任何情况,我们都想要滤除掉低于某值的所有像素值,并假设该阈值设置为20。为此,我们将使用逻辑运算符来执行此任务,最终结果将返回所有索引的真值。

low_pixel=pic<20 # 检查所有值在低像素中是否正确

iflow_pixel.any()==True:
print(low_pixel.shape)# 输出结果

(1079, 1293, 3)

正如之前所说,主机变量,一般并不使用这个名称,但在本文中引用它,这是因为它的行为只保留真值,而不是其他任何形式的值。所以,如果展示low_pixel和pic的形状,我们就会发现它们其实具有相同的形状。

print(pic.shape)print(low_pixel.shape)# 输出(1079,1293,3)
(1079,1293,3)

我们使用全局比较运算符为所有像素值小于200的像素点生成低值滤波器。但是,我们也可以使用此low_pixel数组作为索引将这些低值设置为某些特定值,这些值可能高于或低于先前的像素值。

# 随机选择一个值import random
# 加载原始图像pic=imageio.imread('F:/demo_1.jpg')
# 随机设置一个值,取值范围25~225 
choosenpic[low_pixel]=random.randint(25,225) 
# 展示图像plt.figure(figsize=(10,10))
plt.imshow(pic)plt.show()

掩膜

图像掩膜是一种图像处理技术,被广泛用于去除具有模糊边缘、透明或毛刺部分的照片背景,看起来类似于PS中的一项技术。 下面将带领读者一起创建一个圆盘形状的掩膜。首先,我们测量从图像中心到每个边界像素值的距离,在这里采用应用比较方便的半径,然后使用逻辑运算符创建一个圆盘。这个过程很简单,如下面的代码所示:

if__name__=='__main__':
# 加载图像
pic=imageio.imread('F:/demo_1.jpg')
# 分离行和列
total_row,total_col,layers=pic.shape
''' 创建矢量,Ogrid 是一个不错的方法method of creating a
比如
>>>ogrid[0:5,0:5]  
输出:
[array([[0],[1],[2],[3],[4]]),
array([[0, 1, 2, 3, 4]])]    
'''x,y=np.ogrid[:total_row,:total_col]
# 获取图像的中心值
cen_x,cen_y=total_row/2,total_col/2  
'''  
测量从中心到每个边界像素的距离--> s**2 = (Y-y)**2 + (X-x)**2
'''
distance_from_the_center=np.sqrt((x-cen_x)**2+(y-cen_y)**2)
# 选择半径值
radius=(total_row/2)
# 使用逻辑操作符 '>' 
circular_pic=distance_from_the_center>radius
'''
给所有半径外的像素值分配零值,即黑色
'''
pic[circular_pic]=0
plt.figure(figsize=(10,10))![3]
plt.imshow(pic)
plt.show()

卫星图像处理

作为edX的公开课之一,下面将介绍一些卫星图像及其处理方法,这部分内容是十分有用的,下面对其进行一些处理,做一些分析任务。

# 加载图像
pic=imageio.imread('F:\satimg.jpg')
plt.figure(figsize=(10,10))
plt.imshow(pic)
plt.show()

下面看看它的一些基本信息:

print(f'Shape of the image {pic.shape}')
print(f'hieght {pic.shape[0]} pixels')
print(f'width {pic.shape[1]} pixels')# 输出

Shapeoftheimage(3725,4797,3)height 3725 pixelswidth 4797 pixels

从中可以发现一些有趣的东西,像许多其他可视化结果一样,每个rgb层中的颜色都表示对应的内容。例如,红色强弱表示像素中地理数据点的高度,蓝色强弱表示方位的度量,而绿色表示斜率,这些颜色将有助于我们以更快、更有效的方式传达信息,而不仅是显示数字。

  • 红色像素表示:高度
  • 蓝色像素表示:方位
  • 绿色像素表示:斜率 只需看一下这张彩色图像,训练有素的眼睛就能分辨出海拔是多少,斜率是多少,方位在哪里,所以为这些颜色加载更多含义能够表示更科学的东西,一个好的想法!

检测每个通道的高像素

# 只有红色通道值,像素值高于180

pic=imageio.imread('F:\satimg.jpg')red_mask=pic[:,:,0]<180pic[red_mask]=0plt.figure(figsize=(15,15))plt.imshow(pic)  # 只有绿色通道像素值,像素值高于180

pic=imageio.imread('F:\satimg.jpg')green_mask=pic[:,:,1]<180pic[green_mask]=0plt.figure(figsize=(15,15))plt.imshow(pic)  # 只有蓝色通道像素值,像素值高于180

pic=imageio.imread('F:\satimg.jpg')blue_mask=pic[:,:,2]<180pic[blue_mask]=0plt.figure(figsize=(15,15))plt.imshow(pic)# 使用逻辑与的组合掩膜

pic=imageio.imread('F:\satimg.jpg')final_mask=np.logical_and(red_mask,green_mask,blue_mask)pic[final_mask]=40plt.figure(figsize=(15,15))plt.imshow(pic)

本文分享自微信公众号 - AI科技时讯(aiblog_research)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-07-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python数据科学

1900页数学基础:面向CS的线性代数、拓扑、微积分和最优化

链接:http://www.cis.upenn.edu/~jean/math-basics.pdf

17810
来自专栏程序猿声

10分钟用Python做个微信朋友圈抽奖九宫格

哈哈,笑出猪叫!这个玩法利用了朋友圈发长图会显示中间局部的设定,搞笑之余也为朋友圈广告营销贡献了新思路。

25720
来自专栏腾讯移动品质中心TMQ的专栏

快速探索,音视频技术不再神秘

? 一、采集 - 数据从哪里来? 1.1 采样原理 定义:对连续变化图像在空间坐标上做离散化处理,将模拟信号转变成数字信号的过程,即为图像进行采样。 通俗...

17620
来自专栏相约机器人

使用CoreML和ARKit进行人脸检测和识别

现在已经拥有了自己的项目,并且因为不喜欢使用故事板,所以应用程序以编程方式完成,这意味着没有按钮或开关切换,只需要纯粹的代码。

19920
来自专栏VRPinea

7.29 VR扫描:数字王国配售2.06亿港元股份;The Void将开设25个新门店

近日,数字王国宣布,其公司已配售完成20亿股股份,所得款项约为2.06亿港元。据悉,该资金将用于集团的媒体娱乐分部运营,特别是DD Land项目的投资建设,及一...

6420
来自专栏计算机视觉战队

告诉我我在哪?——目标级别的场景上下文预测(文末附有原文)

计算机视觉领域,利用局部特征、全局特征、深度特征以及上下文特征已经是大家习以为常的操作,尤其是前三种特征的使用,近期对上下文及显著性特征关注较多,今天和大家分享...

18710
来自专栏深度学习和计算机视觉

程序员脱发自救:用计算机视觉技术安全植发

场景描述:面对日益严重的脱发问题,植发已经成了很多人的救命法宝。但植发市场的扩大,以及专业人员的缺乏,也让这项依赖专业医师的项目变得破朔迷离。而人工智能、机器人...

10320
来自专栏web前端基地

H5C3第二节

对于我们眼睛来说,离我们越近的房子,我们会感觉到这个房子越大,离我们越远的房子,就会感觉越小,其实房子的大小都是一样的,只是在视觉上的一种不同。

6720
来自专栏SIGAI学习与实践平台

从单幅图像到双目立体视觉的3D目标检测算法

经典的计算机视觉问题是通过数学模型或者统计学习识别图像中的物体、场景,继而实现视频时序序列上的运动识别、物体轨迹追踪、行为识别等等。然而,由于图像是三维空间在光...

24040
来自专栏FreeBuf

Imagemagick邂逅Getimagesize的那点事儿

前段时间写的文章,在微博上说7月底结束分享一下,总算可以发了。感谢 @voidfyoo 提出的这个问题。

8320

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励