萌新方便自己查询的笔记,记录一些常用的方法,不定时更新~
安装
pip install numpy
pip install opencv-python
import numpy as np
import cv2
注:opencv中通过索引直接读取图片像素时,列在前行在后!即img[y][x]!
注:如果图片文件名中含有中文,会导致出错,需要使用以下带中文路径的特殊写法。
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)
import numpy as np
img = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8), -1)
output_path = "output.jpg"
cv2.imwrite(output_path,img)
import numpy as np
import os
cv2.imencode(os.path.splitext(output_path)[1], img)[1].tofile(output_path)
# 允许图片自由缩放
window_name = "test window"
cv2.namedWindow(window_name,0);
# 显示图片
cv2.imshow(window_name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
或者
cv2.imshow("1", img1)
cv2.imshow("2", img2)
cv2.waitKey(0)
然后按空格切换下一张
注:与直接读入灰度图的效果不完全相同
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)
# 拉普拉斯滤波器
laplacian = cv2.Laplacian(srcImg, cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
# 自定义滤波器,样例为拉普拉斯滤波器
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)
对于高像素图片缩小,使用cv2可能会导致严重的锯齿产生,这种情况下可以使用Image库进行高质量图像缩放。
from PIL import Image
# 将图像从BGR空间转换到RGB空间,如果是三通道图像就去除A图层
(B, G, R, A) = cv2.split(img)
# 四颜色通道合并
img = cv2.merge([R,G,B,A])
# 修改为256x256
img = Image.fromarray(img)
img = img.resize((256,256), Image.ANTIALIAS)
# 使用Image输出到磁盘
img.save(output_path)
需要先转换为Image库的image格式
img.convert('P').save(img_path)
等同于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)
# 垂直水平翻转/旋转180度
img = cv2.flip(img,-1)
# 左转90度
img = cv2.flip(cv2.transpose(img), 0)
# 右转90度
img = cv2.flip(cv2.transpose(img), 1)
# 定义核
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
# 膨胀
img = cv2.dilate(img,kernel,iterations=1)
# 腐蚀
img = cv2.erode(img,kernel,iterations=1)
# 画圆
cv2.circle(img, center, radius, (255, 0, 0), 1)
# 画矩形
cv2.rectangle(img, (x_min, y_min), (x_max, y_max), (0, 255, 0), 1)
# 定义阈值
threshold = 50
# 固定阈值二值化
ret,img=cv2.threshold(gray_img,threshold,255,cv2.THRESH_BINARY_INV)
# 大津法
thresold, img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# 局部自适应二值化
binary = cv2.adaptiveThreshold(gray_img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,3, 5)
import cv2
import numpy as np
img1 = cv2.imread('1.png', 1)
img2 = cv2.imread('2.png', 1)
# 拼接图像
h, w = img1.shape[:2]
result = np.zeros([h, w*2, 3], dtype=img1.dtype)
result[0:h,0:w,:] = img1
result[0:h,w:2*w,:] = img2
# 给图像打标注文字
cv2.putText(result, f"1", (10, 30), cv2.FONT_ITALIC, 1.0, (0, 0, 255), 2)
cv2.putText(result, f"2", (w+10, 30), cv2.FONT_ITALIC, 1.0, (0, 0, 255), 2)
# 写入图像
cv2.imwrite('result.png', result)
用于机器学习输入。
将(length, width, 3)的彩色图片矩阵修改为(3, length, width)的形式。
img = torch.tensor(img, dtype=torch.float32)
# 改变矩阵形状
img = img.permute(2, 0, 1)
针对动态gif图像的操作
安装
pip install imageio
import imageio
注:是mimread(),而不是imread()。
imgs = imageio.mimread("test.gif")
imgs = np.array(imgs)
此时imgs为包含所有numpy矩阵形式图片的一个列表,其中每一个元素都是一个numpy矩阵形式的图片。
output_name = "output.gif"
imageio.mimsave(output_name, imgs, 'GIF')
用于将背景为单色(如蓝色)的证件照片背景色替换为其它颜色(如白色),在人物几乎不含与背景同色衣服的情况下使用。
需要根据输出图片的效果自行调整阈值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)
输入一个三通道彩色图像,手动为其添加一个透明度的第四通道,即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.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)
转换为灰度图,通过拉普拉斯滤波器提取线稿轮廓,通过形态学操作的膨胀和腐蚀来连接结构和去除噪点,最后用二值化增强轮廓与减少噪点。
原图:
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)
最终效果: