整理图像处理相关的代码和问题,方便查阅
文章目录
1 读取图片
法1 opencv
import cv2
image_cv = cv2.imread('0.jpg') # numpy.ndarray, 打开后的size为(h, w, c)
image_gray = cv2.imread('0.jpg', cv2.IMREAD_GRAYSCALE) # 读取为灰度图
法2 PIL
from PIL import Image
image_pil = Image.open('0.jpg') # PIL图片格式,打开后的size为(w, h)
法1法2的结果互相转换
image_pil = Image.fromarray(image_cv) # 1->2
image_numpy = np.array(image_pil) # 2->1, size会变成(h, w, c)
法3 sklearn
import skimage.io as io
image = io.imread('0.jpg') # 直接为RGB
io.imshow(image)
2 图片保存
法1 opencv
img = cv2.imread('0.jpg')
cv2.imwrite(filepath, img) # filepath: 如'./xxx.jpg'
法2 PIL
image = Image.fromarray(img) # 如果img为单通道,则需要在这句后加上 .convert('RGB'),否则会报错
img_resize = image.resize((100, 100), Image.LANCZOS) # 可以进行resize一下
img_resize.save('xxx.jpg', format='jpeg')
3 图像变换
色彩
# 分离颜色通道
b, g, r = cv2.split(img) # 注意顺序为BGR
# 合并
img = cv2.merge((b, g, r)) # 注意双括号
# 更改颜色通道
# OpenCV使用BGR约定存储彩色图像,matplotlib使用RGB约定。
img_color = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32) # 同时修改数据类型
# PIL.Image.convert
img_1 = img.convert('1')
img_L = img.convert('L')
img_RGB = img.convert('RGB')
# numpy的方法
img = img[:, :, ::-1]
大小
# 更改大小
img_size = cv2.resize(img_rgb, (self.width, self.height), cv2.INTER_AREA)
# PIL的方法
# PIL获取图片大小
w = image.width
h = image.height
img_resize = image.resize((w * 2, h * 2), Image.LANCZOS) # Image.LANCZOS表示多相位插值
# 裁剪
img_sub = img[0:100, 0:100]
# 边界填充
top, bottom, left, right = (50, 50, 50, 50) # 四周填充的量
replicate = cv2.copyMakeBorder(img, top, bottom, left, right, borderType=cv2.BORDER_REPLICATE) # 复制填充
constant = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=0) # 常数填充
维度
# 变换维度
torch.Tensor.permute # eg:x.permute(2, 0, 1) # 更改顺序
numpy.transpose # eg:x.transpose(2, 0, 1) # 更改顺序,可用来将HWC,改为CHW
torch.squeeze() # 降维
torch.unsqueeze() # 增维
numpy.newaxis # eg:x[:,np.newaxis,:] # 增维
numpy.squeeze() # 降维
4 图像处理
滤波
# 均值滤波
image_mean = cv2.blur(img, (3, 3))
# 高斯模糊
image_gauss = cv2.GaussianBlur(image, (3, 3), 0) # 参数3为方差
# 中值滤波
image = cv2.medianBlur(image, 15) # 参数2为卷积核的大小
边缘
# 边缘算子
image_canny = cv2.Canny(image,200,250)
形态学
# 形态学
# 开运算:先腐蚀,再膨胀
kernel = np.ones((5, 5), np.uint8)
image_open = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
# 闭运算:先膨胀,再腐蚀
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (35, 8))
image_close = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernelX)
# 膨胀(dilate) 腐蚀(erode)
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (20, 1)) # X方向
kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 18)) # Y方向
image1 = cv2.dilate(image, kernelX)
image2 = cv2.erode(image1, kernelY)
image1 = cv2.erode(image, kernelX)
image2 = cv2.dilate(image1, kernelY)
# 礼帽与黑帽
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) # 礼帽:原始输入-开运算结果
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel) # 黑帽:闭运算-原始输入
像素
# 图片灰度化
image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
# 阈值处理
# 二值化
ret, image_two = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU) # 大律法
ret, image_two = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY) # 超过阈值(参数2)的部分取参数3的值
ret, image_two = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY_INV) # 反转
ret, image_two = cv2.threshold(image, 127, 255, cv2.THRESH_TRUNC) # 大于阈值的部分设为阈值,否则不变
ret, image_two = cv2.threshold(image, 127, 255, cv2.THRESH_TOZERO) # 大于阈值的部分不变,否则设为0
5 绘制
# 展示图像
fig,ax = plt.subplots(1)
fig.set_size_inches(18.5, 10.5)
ax.imshow(img.permute(1, 2, 0)) # 将通道C换到第三位
# 在图像上绘制矩形
rect = patches.Rectangle((xmin,ymin),(xmax-xmin),(ymax-ymin),linewidth=2,edgecolor='r',facecolor='none')
ax.add_patch(rect)
# 添加文字
ax.text(xmin, ymin, f"{label}", horizontalalignment='center', verticalalignment='center',fontsize=20,color='b')
plt.savefig(fullPath) # 若要保存,得在show()之前
plt.show()
6 常见问题
- 图像数据类型是np.float32还是np.uint8
- 图像维度数量,灰度图和RGB,BGR
- C,W,H的相对位置,是CHW,还是HWC
- 图像处理的参数
- 是否被转置