使用python PIL库读取图像,该方法返回一个 Image 对象,Image对象存储着这个图像的格式(jpeg,jpg,ppm等),大小和颜色模式(RGB),它含有一个show()方法用来显示图像:
# 导入PIL库
from PIL import Image
# 使用 Image 类读取图像
img = Image.open("Image-Progcess/image.png")
# 查看图像的信息
print(img.format,img.size,img.mode)
# 显示图像
img.show()
读取图像不需要制定它的格式。
使用Image对象以不同的格式写入图像文件,需要指定它的格式:
# 写入图像
# 引入系统库,提供获取目录的方法
# 导入PIL库
from PIL import Image
import os,sys
# Image对象使用save方法存储图像文件
# 将文件转换为JPEG
# sys.argv[1:]是使用 python file.py [args]调用该python模块时的参数[args]
for infile in sys.argv[1:]:
f,e = os.path.splitext(infile)
outfile = f + ".png"
print(outfile)
if infile != outfile:
try:
img = Image.open("image.png")
print(img.size)
with Image.open(outfile) as im:
print(im.size)
im.save(f+'.jpg')
im.save(f+'.ppm')
im.save(f+'.bmp')
except OSError as e:
print('cannot convert',str(e))BMP格式,也称为Bitmap (位图),是Windows系统中广泛使用的图像文件格式,由于它可以不做任何变换的保存图像像素域的数据,它成为了我们获取RAW数据的重要来源。
BMP文件的数据按照文件头开始的先后顺序分为四个部分:
位图是用一个位数组表示,32位和16位表示颜色质量,即每个像素用多少比特位表示 (1、4、8、15、24、32 或 64) ,这个数字在文件头中指定。
位图的色数由调色板决定,只有4,8位图像才会使用调色板数据,16,24,32位图像不需要调色板数据,调色板最多只需要256项(索引0 - 255)。调色板的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。
类型 | 优点 | 缺点 | 应用场景 | 相同图片大小比较 |
|---|---|---|---|---|
BMP | 无损保存,图质最好,广泛支持 | 体积太大,不利于保存和网络传输 | 57.1MB | |
GIF | 动画存储格式 | 最多256色,画质差 | ||
PNG | 几乎无损的压缩和较好的质量 | 质量较高 | 1.4MB | |
JPG | 压缩率高,利于网络传输 | 质量一般 | 车牌识别 | 425KB |
奇异值分解是矩阵分解方法之一,它将矩阵分解为3个子矩阵,即U,S,V,其中U是左特征向量,S是奇异值的对角矩阵,V称为右特征向量。
使用numpy的 linalg.svd() 方法重建图像的SVD矩阵。
linalg.svd(矩阵,full_matrices=True,compute_uv=True,hermitian=False)参数:
使用linalg.svd()方法分解矩阵,查看图像具有多少个线性无关的特征向量。
# 导入模块
import requests
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 分配并打开图像
url = 'https://media.geeksforgeeks.org/wp-content/cdn-uploads/20210401173418/Webp-compressed.jpg'
response = requests.get(url, stream=True)
with open('image.png', 'wb') as f:
f.write(response.content)
img = cv2.imread('image.png')
# 将图像转换为灰度以加快速度
# 计算。
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 计算SVD
u, s, v = np.linalg.svd(gray_image, full_matrices=False)
# 检查矩阵的形状
print(f'u.shape:{u.shape},s.shape:{s.shape},v.shape:{v.shape}')
输出形状表明该图像具有3648个线性无关的特征向量。
# 导入模块
import seaborn as sns
var_explained = np.round(s**2/np.sum(s**2), decimals=6)
# 方差解释顶部奇异向量
print(f'variance Explained by Top 20 singular values:\n{var_explained[0:20]}')
sns.barplot(x=list(range(1, 21)),
y=var_explained[0:20], color="dodgerblue")
plt.title('Variance Explained Graph')
plt.xlabel('Singular Vector', fontsize=16)
plt.ylabel('Variance Explained', fontsize=16)
plt.tight_layout()
plt.show()
上面的方差解释图表明,大约99.77%的信息是由第一个特征向量及其相应的特征值本身解释的。
使用不同个数的奇异值来重组图像:
# 用不同数量的奇异值绘制图像
comps = [3648, 1, 5, 10, 15, 20]
plt.figure(figsize=(12, 6))
for i in range(len(comps)):
low_rank = u[:, :comps[i]] @ np.diag(s[:comps[i]]) @ v[:comps[i], :]
if(i == 0):
plt.subplot(2, 3, i+1),
plt.imshow(low_rank, cmap='gray'),
plt.title(f'Actual Image with n_components = {comps[i]}')
else:
plt.subplot(2, 3, i+1),
plt.imshow(low_rank, cmap='gray'),
plt.title(f'n_components = {comps[i]}')
侵蚀的基本思想就像土壤侵蚀一样,它侵蚀了前景对象的边界(始终尽量保持前景为白色)。那么它有什么作用呢?内核在图像中滑动(如在 2D 卷积中)。仅当内核下的所有像素都为 1 时,原始图像中的像素(1 或 0)才会被视为 1,否则它会被侵蚀(使其为零)。
腐蚀操作是将结构元素覆盖下的中心像素点的值用最小值替换 :
import cv2
import numpy as np
img = cv2.imread('j.png',0)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)膨胀操作是将结构元素覆盖下的中心像素点的值用最大值替换:
dilation = cv2.dilate(img,kernel,iterations = 1)
HoughCircles() 函数仅接受单通道图像,在使用图像之前要先使用 cv2.cvtColor() 函数获取灰度图像:
# 灰色图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)使用霍夫圆变换的画圆函数:
# 画圆
def drawCircle(image):
# 霍夫圆变换
circles = cv2.HoughCircles(
image,
cv2.HOUGH_GRADIENT,
1,
20,
param1=50,
param2=30,
minRadius=0,
maxRadius=0
)
# 确保至少找到了一些圆圈
output = image.copy()
if circles is not None:
# 将圆的 (x, y) 坐标和半径转换为整数
circles = np.round(circles[0, :]).astype("int")
# 循环 (x, y) 坐标和圆的半径
for (x, y, r) in circles:
# 在输出图像中绘制圆形,然后绘制矩形
# 对应圆心
cv2.circle(output, (x, y), r, (0, 255, 0), 4)
# 显示输出图像
cv2.imshow("output", np.hstack([image, output]))
cv2.waitKey(0)1) 使用模糊灰度图像和霍夫圆变换
img = cv2.imread('Image-Progcess/image1.png')
# 灰色图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 模糊灰度图像
blurred = cv2.medianBlur(gray,5)
# 画圆
drawCircle(blurred)
2) 使用腐蚀运算和霍夫圆变换
erosion = cv2.erode(img,kernel,iterations = 1)
3) 使用膨胀运算
dilation = cv2.dilate(img,kernel,iterations = 1)

开操作是首先对图像进行腐蚀操作,然后在对图像进行膨胀操作,开操作可以断开两个对象的连接性。实现对象分离。
闭操作使用结构元素对图像先膨胀后腐蚀,正好跟开操作的顺序相反,但是闭操作绝对不是开操作的反操作结果。
形态学的梯度操作是图像膨胀与腐蚀结果之间的不同 :
# 开运算
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# 闭运算
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
#形态梯度
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
为了检测圆形或任何其他几何形状,我们首先需要检测图像中存在的对象的边缘。
图像中的边缘是颜色急剧变化的点。例如,白底红球的边缘是一个圆。为了识别图像的边缘,一种常用的方法是计算图像梯度。
找到图像的轮廓:
cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 导入所需库
import numpy as np
import imutils
import cv2
# 转换为灰度图像
image = cv2.imread('Image-Progcess/tiaoxingma2.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 使用Scharr算子的边缘检测方法
ddepth = cv2.CV_32F if imutils.is_cv2() else cv2.CV_32F
gradX = cv2.Sobel(gray, ddepth=ddepth, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(gray, ddepth=ddepth, dx=0, dy=1, ksize=-1)
gradient = cv2.subtract(gradX,gradY)
gradient = cv2.convertScaleAbs(gradient)
#去除噪声
## 模糊和阈值化处理
blurred = cv2.blur(gradient,(9, 9))
(_, thresh) = cv2.threshold(blurred, 231, 255, cv2.THRESH_BINARY)
## 形态学处理
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
closed = cv2.erode(closed, None, iterations=4)
closed = cv2.dilate(closed, None, iterations=4)
# 确定检测轮廓,画出检测框
cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect) if imutils.is_cv2() else cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
cv2.imshow("Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。