① 读取图片
python基础——读取图片
图像后缀名的转换:
要注意的是:对于彩色图像,不管其格式是png,还是bmp,或者jpg,
在PIL中 ,使用Image模块的open()函数打开后,返回的图像对象的模式都是毁型 RGB ,对于灰度图像,不管其图像格式是PNG,还是BMP,JPG,打开后,其模式为灰度L。
PNG BMP JPG彩色图像格式之间的转换:可以通过Image模块的open函数和save函数,具体来说,在打开这些图像时,PIL会将他们解码成三通道的RGB图像。用户可以基于RGB进行处理。处理完毕后可以将其处理结果保存成PNG BMP JPG中任何格式。
PNG BMP JPG灰度图像格式之间的转换,同理也可以通过类似途径,只是解码后时模式为L的图像。
python库可以用来读取图片的库
1. PIL.Image.open
无论是jpg还是png都能准确读取,PIL.Image.open 不直接返回numpy对象,可以用numpy提供的函数进行转换;
其他模块都直接返回numpy.ndarray对象,通道顺序为RGB,通道值得默认范围为0-255。
拓展:
利用PIL中的Image函数读取出来不是array格式,这时候需要用消困np.asarray() 或者np.array()函数 。
区别:np.array() 是深拷贝,np.asarray() 是浅拷贝
关于深拷贝和浅拷贝,这里给出一个说明:
Python 中的对象之间赋值时是按引用传递的,如果需要拷贝对象,需要使用标准库中的模块。
1. . 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。
2. .deep 深拷贝 拷贝对象及其子对象
一个很好的例子:
2. cv2.imread
使用opencv读取图像,直接返回numpy.ndarray 对象,通道顺序为BGR ,注意是BGR,通道值默认范围0-255
cv2.imread():读入图片,共两个参数:第一个参数为要读入的图片文件名,第二个参数为如何读取图片(cv2.IMREAD_COLOR:读入一副彩色图片;cv2.IMREAD_GRAYSCALE:灰度图片;cv2.IMREAD_UNCHANGED:读入一幅图片,并包括其alpha通道。)
cv2.imread()不能有中文路径,否则读取不出来
cv2.imread() 读出来同样是array形式,但是如果是单通道的图,读出来的是三通道的。
3. matplotlib.image.imread
用于显示图片matplotlib 用于读取图片并且读取出来就是array格式
解决使用plt.savefig 保存图片时一片空白 : 在plt.show() 之前调用 plt.savefig();
4. scipy.ndimage.imread
scipy.ndimage.imread(*args, **kwds) Use ``matplotlib.pyplot.imread`` instead.
Returns:imread:ndarray(多维数组)
5. scipy.misc.imread
scipy.misc.imread(name, flatten=False, mode=None)
Use ``imageio.imread`` instead.
返回:imread: ndarray。通过读取图像获得的阵列 。读出来是array 形式,并且按照(H,拿余念W,C)形式保存
4. skimage.io.imread
scikit-image和numpy,matplotlib,scikit-learn等包都是Scipy项目的成员,通用numpy数组作为基本数据格式。在python中载入包名为skimage:所得即为numpy数组。
io.imread读出图片格式是uint8(unsigned int);value是numpy array;图像数据是以RGB的格式进行存储的,通道值默认范围0-255。
② 数字图像处理Python实现图像灰度变换、直方图均衡、均值滤波
import CV2
import
import numpy as np
import random
使用的是pycharm
因为最近看了《银翼杀手2049》,里面Joi实在是太好看了所以原图像就用Joi了
要求是灰度图像,所以第一步先把图像转化成灰度图像
# 读入原始图像
img = CV2.imread('joi.jpg')
# 灰度化处理
gray = CV2.cvtColor(img, CV2.COLOR_BGR2GRAY)
CV2.imwrite('img.png', gray)
第一个任务是利用分段函数增强灰度对比,我自己随便写了个函数大致是这样的
def chng(a):
if a < 255/3:
b = a/2
elif a < 255/3*2:
b = (a-255/3)*2 + 255/6
else:
b = (a-255/3*2)/2 + 255/6 +255/3*2
return b
rows = img.shape[0]
cols = img.shape[1]
cover = .deep(gray)
for i in range(rows):
for j in range(cols):
cover[i][j] = chng(cover[i][j])
CV2.imwrite('cover.png', cover)
下一步是直方图均衡化
# histogram equalization
def hist_equal(img, z_max=255):
H, W = img.shape
# S is the total of pixels
S = H * W * 1.
out = img.()
sum_h = 0.
for i in range(1, 255):
ind = np.where(img == i)
sum_h += len(img[ind])
z_prime = z_max / S * sum_h
out[ind] = z_prime
out = out.astype(np.uint8)
return out
covereq = hist_equal(cover)
CV2.imwrite('covereq.png', covereq)
在实现滤波之前先添加高斯噪声和椒盐噪声(代码来源于网络)
不知道这个椒盐噪声的名字是谁起的感觉隔壁小孩都馋哭了
用到了random.gauss()
percentage是噪声占比
def GaussianNoise(src,means,sigma,percetage):
NoiseImg=src
NoiseNum=int(percetage*src.shape[0]*src.shape[1])
for i in range(NoiseNum):
randX=random.randint(0,src.shape[0]-1)
randY=random.randint(0,src.shape[1]-1)
NoiseImg[randX, randY]=NoiseImg[randX,randY]+random.gauss(means,sigma)
if NoiseImg[randX, randY]< 0:
NoiseImg[randX, randY]=0
elif NoiseImg[randX, randY]>255:
NoiseImg[randX, randY]=255
return NoiseImg
def PepperandSalt(src,percetage):
NoiseImg=src
NoiseNum=int(percetage*src.shape[0]*src.shape[1])
for i in range(NoiseNum):
randX=random.randint(0,src.shape[0]-1)
randY=random.randint(0,src.shape[1]-1)
if random.randint(0,1)<=0.5:
NoiseImg[randX,randY]=0
else:
NoiseImg[randX,randY]=255
return NoiseImg
covereqg = GaussianNoise(covereq, 2, 4, 0.8)
CV2.imwrite('covereqg.png', covereqg)
covereqps = PepperandSalt(covereq, 0.05)
CV2.imwrite('covereqps.png', covereqps)
下面开始均值滤波和中值滤波了
就以n x n为例,均值滤波就是用这n x n个像素点灰度值的平均值代替中心点,而中值就是中位数代替中心点,边界点周围补0;前两个函数的作用是算出这个点的灰度值,后两个是对整张图片进行
#均值滤波模板
def mean_filter(x, y, step, img):
sum_s = 0
for k in range(x-int(step/2), x+int(step/2)+1):
for m in range(y-int(step/2), y+int(step/2)+1):
if k-int(step/2) 0 or k+int(step/2)+1 > img.shape[0]
or m-int(step/2) 0 or m+int(step/2)+1 > img.shape[1]:
sum_s += 0
else:
sum_s += img[k][m] / (step*step)
return sum_s
#中值滤波模板
def median_filter(x, y, step, img):
sum_s=[]
for k in range(x-int(step/2), x+int(step/2)+1):
for m in range(y-int(step/2), y+int(step/2)+1):
if k-int(step/2) 0 or k+int(step/2)+1 > img.shape[0]
or m-int(step/2) 0 or m+int(step/2)+1 > img.shape[1]:
sum_s.append(0)
else:
sum_s.append(img[k][m])
sum_s.sort()
return sum_s[(int(step*step/2)+1)]
def median_filter_go(img, n):
img1 = .deep(img)
for i in range(img.shape[0]):
for j in range(img.shape[1]):
img1[i][j] = median_filter(i, j, n, img)
return img1
def mean_filter_go(img, n):
img1 = .deep(img)
for i in range(img.shape[0]):
for j in range(img.shape[1]):
img1[i][j] = mean_filter(i, j, n, img)
return img1
完整main代码如下:
if __name__ == "__main__":
# 读入原始图像
img = CV2.imread('joi.jpg')
# 灰度化处理
gray = CV2.cvtColor(img, CV2.COLOR_BGR2GRAY)
CV2.imwrite('img.png', gray)
rows = img.shape[0]
cols = img.shape[1]
cover = .deep(gray)
for i in range(rows):
for j in range(cols):
cover[i][j] = chng(cover[i][j])
CV2.imwrite('cover.png', cover)
covereq = hist_equal(cover)
CV2.imwrite('covereq.png', covereq)
covereqg = GaussianNoise(covereq, 2, 4, 0.8)
CV2.imwrite('covereqg.png', covereqg)
covereqps = PepperandSalt(covereq, 0.05)
CV2.imwrite('covereqps.png', covereqps)
meanimg3 = mean_filter_go(covereqps, 3)
CV2.imwrite('medimg3.png', meanimg3)
meanimg5 = mean_filter_go(covereqps, 5)
CV2.imwrite('meanimg5.png', meanimg5)
meanimg7 = mean_filter_go(covereqps, 7)
CV2.imwrite('meanimg7.png', meanimg7)
medimg3 = median_filter_go(covereqg, 3)
CV2.imwrite('medimg3.png', medimg3)
medimg5 = median_filter_go(covereqg, 5)
CV2.imwrite('medimg5.png', medimg5)
medimg7 = median_filter_go(covereqg, 7)
CV2.imwrite('medimg7.png', medimg7)
medimg4 = median_filter_go(covereqps, 7)
CV2.imwrite('medimg4.png', medimg4)
③ python处理图片数据
目录
1.机器是如何存储图像的?
2.在Python中读取图像数据
3.从图像数据中提取特征的方法#1:灰度像素值特征
4.从图像数据中提取特征的方法#2:通道的平均像素值
5.从图像数据中提取特征的方法#3:提取边缘
是一张数字8的图像,仔细观察就会发现,图像是由小方格组成的。这些小方格被称为像素。
但是要注意,人们是以视觉的形式观察图像的,可以轻松区分边缘和颜色,从而识别图片中的内容。然而机器很难做到这一点,它们以数字的形式存储图像。请看下图:
机器以数字矩阵的形式储存图像,矩阵大小取决于任意给定图像的像素数。
假设图像的尺寸为180 x 200或n x m,这些尺寸基本上是图像中的像素数(高x宽)。
这些数字或像素值表示像素的强度或亮度,较小的数字(接近0)表示黑色,较大的数字(接近255)表示白色。通过分析下面的图像,读者就会弄懂到目前为止所学到的知识。
下图的尺寸为22 x 16,读者可以通过计算像素数来验证:
图片源于机器学习应用课程
刚才讨论的例子是黑白图像,如果是生活中更为普遍的彩色呢?你是否认为彩色图像也以2D矩阵的形式存储?
彩色图像通常由多种颜色组成,几乎所有颜色都可以从三原色(红色,绿色和蓝色)生成。
因此,如果是彩色图像,则要用到三个矩阵(或通道)——红、绿、蓝。每个矩阵值介于0到255之间,表示该像素的颜色强度。观察下图来理解这个概念:
图片源于机器学习应用课程
左边有一幅彩色图像(人类可以看到),而在右边,红绿蓝三个颜色通道对应三个矩阵,叠加三个通道以形成彩色图像。
请注意,由于原始矩阵非常大且可视化难度较高,因此这些不是给定图像的原始像素值。此外,还可以用各种其他的格式来存储图像,RGB是最受欢迎的,所以笔者放到这里。读者可以在此处阅读更多关于其他流行格式的信息。
用Python读取图像数据
下面开始将理论知识付诸实践。启动Python并加载图像以观察矩阵:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from skimage.io import imread, imshow
image = imread('image_8_original.png', as_gray=True)
imshow(image)
#checking image shape
image.shape, image
(28,28)
矩阵有784个值,而且这只是整个矩阵的一小部分。用一个LIVE编码窗口,不用离开本文就可以运行上述所有代码并查看结果。
下面来深入探讨本文背后的核心思想,并探索使用像素值作为特征的各种方法。
方法#1:灰度像素值特征
从图像创建特征最简单的方法就是将原始的像素用作单独的特征。
考虑相同的示例,就是上面那张图(数字‘8’),图像尺寸为28×28。
能猜出这张图片的特征数量吗?答案是与像素数相同!也就是有784个。
那么问题来了,如何安排这784个像素作为特征呢?这样,可以简单地依次追加每个像素值从而生成特征向量。如下图所示:
下面来用Python绘制图像,并为该图像创建这些特征:
image = imread('puppy.jpeg', as_gray=True)
image.shape, imshow(image)
(650,450)
该图像尺寸为650×450,因此特征数量应为297,000。可以使用NumPy中的reshape函数生成,在其中指定图像尺寸:
#pixel features
features = np.reshape(image, (660*450))
features.shape, features
(297000,)
array([0.96470588, 0.96470588, 0.96470588, ..., 0.96862745, 0.96470588,
0.96470588])
这里就得到了特征——长度为297,000的一维数组。很简单吧?在实时编码窗口中尝试使用此方法提取特征。
但结果只有一个通道或灰度图像,对于彩色图像是否也可以这样呢?来看看吧!
方法#2:通道的平均像素值
在读取上一节中的图像时,设置了参数‘as_gray = True’,因此在图像中只有一个通道,可以轻松附加像素值。下面删除参数并再次加载图像:
image = imread('puppy.jpeg')
image.shape
(660, 450, 3)
这次,图像尺寸为(660,450,3),其中3为通道数量。可以像之前一样继续创建特征,此时特征数量将是660*450*3 = 891,000。
或者,可以使用另一种方法:
生成一个新矩阵,这个矩阵具有来自三个通道的像素平均值,而不是分别使用三个通道中的像素值。
下图可以让读者更清楚地了解这一思路:
这样一来,特征数量保持不变,并且还能考虑来自图像全部三个通道的像素值。
image = imread('puppy.jpeg')
feature_matrix = np.zeros((660,450))
feature_matrix.shape
(660, 450)
现有一个尺寸为(660×450×3)的三维矩阵,其中660为高度,450为宽度,3是通道数。为获取平均像素值,要使用for循环:
for i in range(0,iimage.shape[0]):
for j in range(0,image.shape[1]):
feature_matrix[i][j] = ((int(image[i,j,0]) + int(image[i,j,1]) + int(image[i,j,2]))/3)
新矩阵具有相同的高度和宽度,但只有一个通道。现在,可以按照与上一节相同的步骤进行操作。依次附加像素值以获得一维数组:
features = np.reshape(feature_matrix, (660*450))
features.shape
(297000,)
方法#3:提取边缘特征
请思考,在下图中,如何识别其中存在的对象:
识别出图中的对象很容易——狗、汽车、还有猫,那么在区分的时候要考虑哪些特征呢?形状是一个重要因素,其次是颜色,或者大小。如果机器也能像这样识别形状会怎么样?
类似的想法是提取边缘作为特征并将其作为模型的输入。稍微考虑一下,要如何识别图像中的边缘呢?边缘一般都是颜色急剧变化的地方,请看下图:
笔者在这里突出了两个边缘。这两处边缘之所以可以被识别是因为在图中,可以分别看到颜色从白色变为棕色,或者由棕色变为黑色。如你所知,图像以数字的形式表示,因此就要寻找哪些像素值发生了剧烈变化。
假设图像矩阵如下:
图片源于机器学习应用课程
该像素两侧的像素值差异很大,于是可以得出结论,该像素处存在显着的转变,因此其为边缘。现在问题又来了,是否一定要手动执行此步骤?
当然不!有各种可用于突出显示图像边缘的内核,刚才讨论的方法也可以使用Prewitt内核(在x方向上)来实现。以下是Prewitt内核:
获取所选像素周围的值,并将其与所选内核(Prewitt内核)相乘,然后可以添加结果值以获得最终值。由于±1已经分别存在于两列之中,因此添加这些值就相当于获取差异。
还有其他各种内核,下面是四种最常用的内核:
图片源于机器学习应用课程
现在回到笔记本,为同一图像生成边缘特征:
#importing the required libraries
import numpy as np
from skimage.io import imread, imshow
from skimage.filters import prewitt_h,prewitt_v
import matplotlib.pyplot as plt
%matplotlib inline
#reading the image
image = imread('puppy.jpeg',as_gray=True)
#calculating horizontal edges using prewitt kernel
edges_prewitt_horizontal = prewitt_h(image)
#calculating vertical edges using prewitt kernel
edges_prewitt_vertical = prewitt_v(image)
imshow(edges_prewitt_vertical, cmap='gray')
④ python图像处理库 哪个好 知乎
1.scikit-image
scikit-image是一个开源的Python包,适用于numpy数组。它实现了用于研究,教育和工业应用的算法和实用工具。即使是那些刚接触Python生态系统的人,它也是一个相当简单直接的库。此代码是由活跃的志愿者社区编写的,具有高质量和同行评审的性质。
2.Numpy
Numpy是Python编程的核心库之一,并为数组提供支持。图像本质上是包含数据点像素的标准Numpy数组。因此,我们可以通过使用基本的NumPy操作,例如切片、掩膜和花式索引,来修改图像的像素值。可以使用skimage加载图像并使用matplotlib显示图像。
3.Scipy
scipy是Python的另一个类似Numpy的核心科学模块,可用于基本的图像操作和处理任务。特别是子模块scipy.ndimage,提供了在n维NumPy数组上操作的函数。该包目前包括线性和非线性滤波,二值形态学,B样条插值和对象测量等功能函数。
4. PIL/Pillow
PIL是Python编程语言的一个免费库,它支持打开、操作和保存许多不同的文件格式的图像。然而,随着2009年的最后一次发布,它的开发停滞不前。但幸运的是还有Pillow,一个PIL积极开发的且更容易安装的分支,它能运行在所有主要的操作系统,并支持Python3。这个库包含了基本的图像处理功能,包括点运算、使用一组内置卷积核的滤波和色彩空间的转换。
5.OpenCV-Python
OpenCV是计算机视觉应用中应用最广泛的库之一
。OpenCV-Python是OpenCV的python版API。OpenCV-Python的优点不只有高效,这源于它的内部组成是用C/C++编写的,而且它还容易编写和部署。这使得它成为执行计算密集型计算机视觉程序的一个很好的选择。
6.SimpleCV
SimpleCV也是一个用于构建计算机视觉应用程序的开源框架。有了它,你就可以访问几个高性能的计算机视觉库,如OpenCV,而且不需要先学习了解位深度、文件格式、颜色空间等。它的学习曲线大大小于OpenCV,正如它们的口号所说“计算机视觉变得简单”。
7.Mahotas
Mahotas是另一个计算机视觉和图像处理的Python库。它包括了传统的图像处理功能例如滤波和形态学操作以及更现代的计算机视觉功能用于特征计算,包括兴趣点检测和局部描述符。该接口是Python语言,适合于快速开发,但是算法是用C语言实现的,并根据速度进行了调优。Mahotas库速度快,代码简洁,甚至具有最小的依赖性。
8.SimpleITK
ITK或者Insight Segmentation and Registration
Toolkit是一个开源的跨平台系统,为开发人员提供了一套广泛的图像分析软件工具
。其中,SimpleITK是建立在ITK之上的简化层,旨在促进其在快速原型设计、教育、解释语言中的应用。SimpleITK是一个图像分析工具包,包含大量支持一般过滤操作、图像分割和匹配的组件。SimpleITK本身是用C++写的,但是对于包括Python以内的大部分编程语言都是可用的。
9.pgmagick
pgmagick是GraphicsMagick库的一个基于python的包装。GraphicsMagick图像处理系统有时被称为图像处理的瑞士军刀。它提供了一个具有强大且高效的工具和库集合,支持以88种主要格式读取、写入和操作图像。
10.Pycairo
Pycairo是图像处理库cairo的一组Python捆绑。Cairo是一个用于绘制矢量图形的2D图形库。矢量图形很有趣,因为它们在调整大小或转换时不会失去清晰度。Pycairo是cairo的一组绑定,可用于从Python调用cairo命令。