python图片处理常用操作笔记
萌新方便自己查询的笔记,记录一些常用的方法,不定时更新~
1. 静态图片操作笔记
安装库
安装
pip install numpy
pip install opencv-python
导入库
import numpy as np
import cv2
读写静态图片
注:如果图片文件名中含有中文,会导致出错,疑似编码问题。
从磁盘读取图片
img_path = "input.jpg"
# 读取单通道黑白图片
img = cv2.imread(img_path,0)
# 读取三通道彩色图片
img = cv2.imread(img_path,1)
# 读取四通道PNG图片,第四通道alpha为透明度
img_path = "input.png"
img = cv2.imread(img_path,-1)
将图片写入磁盘
output_path = "output.jpg"
cv2.imwrite(output_path,img)
用cv2显示图片
# 允许图片自由缩放
window_name = "test window"
cv2.namedWindow(window_name,0);
# 显示图片
cv2.imshow(window_name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
将彩色图转换为灰度图
注:与直接读入灰度图的效果不完全相同
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
过滤图片中的噪点
根据具体需求选择不同的滤波器。
# 使用3x3的均值滤波器
img = cv2.blur(img, (3, 3))
# 中值滤波
img = cv2.medianBlur(img, 3)
# 高斯滤波
img = cv2.GaussianBlur(img,(3,3),0)
# 自定义滤波器,样例为拉普拉斯滤波器
kernal = np.array([[0, -1, 0], [-1, 4, -1], [0, -1, 0]])
img = cv2.filter2D(img, -1, kernal)
缩放图片的长宽
resize与reshape不同:
reshape是重塑矩阵形状,不改变数据总量,如将(2,3)改为(1,6)。
resize是任意尺度缩放图片,会改变矩阵包含的总元素数量。
# 设定新的图片长宽
new_size = (224,224)
# 缩放图片
img = cv2.resize(img,new_size)
图片截取
等同于numpy的高维矩阵切片,如:
img = img[:200,100:,:]
颜色通道拆分与合并
# 三颜色通道拆分
(B, G, R) = cv2.split(img)
# 三颜色通道合并
img = cv2.merge([B,G,R])
# 四颜色通道拆分
(B, G, R, A) = cv2.split(img)
# 四颜色通道合并
img = cv2.merge([B,G,R,A])
直方图均衡化
# 对单通道使用,多通道需要先拆分再对每个通道分别均衡化
img = cv2.equalizeHist(img)
图片翻转
# 垂直翻转
img = cv2.flip(img,0)
# 水平翻转
img = cv2.flip(img,1)
# 垂直水平翻转
img = cv2.flip(img,-1)
形态学操作
# 定义核
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
# 膨胀
img = cv2.dilate(img,kernel,iterations=1)
# 腐蚀
img = cv2.erode(img,kernel,iterations=1)
二值化
# 定义阈值
threshold = 50
# 二值化
ret,img=cv2.threshold(img,threshold,255,cv2.THRESH_BINARY_INV)
高维矩阵转置
用于机器学习输入。
将(length, width, 3)的彩色图片矩阵修改为(3, length, width)的形式。
tensor中的用法,需要导入torch包。
img = torch.tensor(img, dtype=torch.float32)
# 改变矩阵形状
img = img.permute(2, 0, 1)
2. 动态图片操作笔记
针对动态gif图像的操作
安装库
安装
pip install imageio
导入库
import imageio
读取gif图片
注:是mimread(),而不是imread()。
imgs = imageio.mimread("test.gif")
imgs = np.array(imgs)
此时imgs为包含所有numpy矩阵形式图片的一个列表,其中每一个元素都是一个numpy矩阵形式的图片。
写出gif图片
output_name = "output.gif"
imageio.mimsave(output_name, imgs, 'GIF')
3. 一些简单功能实现笔记
3.1 单色背景照片背景色替换
用于将背景为单色(如蓝色)的证件照片背景色替换为其它颜色(如白色),在人物几乎不含与背景同色衣服的情况下使用。
需要根据输出图片的效果自行调整阈值max_difference的大小。
import cv2
import numpy as np
from scipy.spatial.distance import cdist
# 输入文件名
input_img = 'input.jpg'
img = cv2.imread(input_img,1)
# 配置阈值,与取样点之间的最大相似值误差,根据输出效果调整
max_difference = 150
# 取出左上角第一个点作为取样点
sample = img[0][0]
# 将图片拉平用于计算
input_data = img.reshape((img.shape[0] * img.shape[1], 3))
# 计算所有图片与采样点之间的曼哈顿距离
differences = cdist(input_data, [sample], 'cityblock')
# 还原距离矩阵的形状,此时为单通道,仅包含距离
differences = differences.reshape((img.shape[0], img.shape[1]))
# 将背景替换为新的颜色,此处设置为白色
change = np.array([255,255,255])
# 深拷贝一个输入图片用于输出
output = img.copy()
for i in range(img.shape[0]):
# 打印工作进度
if i % 500 == 0:
print(i,"/",img.shape[0])
# 如果距离小于阈值,改变颜色
for j in range(img.shape[1]):
if differences[i][j] < max_difference:
output[i][j] = change
# 输出文件名
output_name = 'output.jpg'
cv2.imwrite(output_name,output)
3.2 为图片增加透明度图层并自定义透明度
输入一个三通道彩色图像,手动为其添加一个透明度的第四通道,即alpha通道,自定义透明度数据,然后输出为png图像。
import numpy as np
import cv2
# 输入一个三通道图像
img = cv2.imread('test.jpg',1)
# 拆分颜色通道
(B, G, R) = cv2.split(img)
# 自定义一个初始全为0的透明度图层
A = np.zeros(B.shape, dtype="uint8")
# 自定义调整透明度,透明度在0-255之间取值
# 这里将图片的一部分透明度调整为155,其余部分保持为0用作示例
A[:70,:] = 155
# 将透明度图层并入四通道图像
img = cv2.merge([B, G, R, A])
# 输出png格式的图片
cv2.imwrite('output.png',img)
3.3 截图提取微信表情图片
将3.1与3.2的代码思路整合一下,从而实现利用截图获取微信聊天中的表情图片……愚蠢的微信表情图片居然不能直接选择保存到本地???,并且让程序自动去除截图中的背景,将原本透明的图片背景仍然输出为透明的状态从而实现盗别人的图片作为自己头像的邪恶目的。
import numpy as np
import cv2
from scipy.spatial.distance import cdist
# config,配置参数,根据实际输出情况调整
# 在截图的四周切除百分之多少的边框
cut_percent = 4
# 配置阈值,与取样点之间的最大相似值误差
max_difference = 50
# 输入文件名
input_img = 'weixin_img.png'
# 输出文件名
output_name = 'output.png'
img = cv2.imread(input_img,1)
# 去除截图边缘边框(按照百分比切除)
img = img[int(img.shape[0]*(cut_percent/100)):int(img.shape[0]*(1-cut_percent/100)),\
int(img.shape[1]*(cut_percent/100)):int(img.shape[1]*(1-cut_percent/100)),:]
# 取出左上角第一个点作为取样点
sample = img[0][0]
# 将图片拉平用于计算
input_data = img.reshape((img.shape[0] * img.shape[1], 3))
# 计算所有图片与采样点之间的曼哈顿距离
differences = cdist(input_data, [sample], 'cityblock')
# 还原距离矩阵的形状,此时为单通道,仅包含距离
differences = differences.reshape((img.shape[0], img.shape[1]))
# 创建透明图层,默认全透明
A = np.zeros(img.shape[:2], dtype="uint8")
for i in range(img.shape[0]):
# 打印工作进度
if i % 500 == 0:
print(i,"/",img.shape[0])
# 如果距离大于阈值,设置为不透明
for j in range(img.shape[1]):
if differences[i][j] > max_difference:
A[i][j] = 255
# 生成带有透明图层的四通道输出图片
(B, G, R) = cv2.split(img)
output = cv2.merge([B, G, R, A])
cv2.imwrite(output_name,output)
3.4 将彩色图转换为黑白线稿
转换为灰度图,通过拉普拉斯滤波器提取线稿轮廓,通过形态学操作的膨胀和腐蚀来连接结构和去除噪点,最后用二值化增强轮廓与减少噪点。
原图:
import cv2
import numpy as np
img_path = "input.png"
# 读取单通道黑白图片
img = cv2.imread(img_path,0)
# 拉普拉斯滤波器
kernal = np.array([[0, -1, 0], [-1, 4, -1], [0, -1, 0]])
img = cv2.filter2D(img, -1, kernal)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
# 膨胀两次
img = cv2.dilate(img,kernel,iterations=2)
# 腐蚀两次
img = cv2.erode(img,kernel,iterations=2)
# 二值化
ret,img=cv2.threshold(img,50,255,cv2.THRESH_BINARY_INV)
# 输出
output_path = "output.jpg"
cv2.imwrite(output_path,img)
最终效果: