opencv提取图像中矩形区域并裁剪
概述
代码适用于图像中仅有一个矩形的情况,对图像中的矩形区域进行边缘的做标提取,完成对矩形区域的裁剪,裁剪完后对图像进行了填充、旋转(若图像倾斜)
思路
- 读取图像,将图像转成灰度图
- 对图像进行开运算,将烟盒以外的污点去除
- 提取图像最小外接矩形
- 通过最小外接矩形的四个点坐标对图像进行填充
- 将图像翻转至水平角度
- 用图像开操作(先腐蚀、后膨胀)
- 旋转图像(图像不水平情况下)
- 写入覆盖原图
实现
import os
import numpy as np
import cv2
def crop_picture_pro(path):
img_path = path
files = os.listdir(img_path)
files.sort()
for bmpFile in files:
if bmpFile.endswith('.bmp'):
# 读取图像并转化为灰度图
image = cv2.imread((img_path + str(bmpFile)))
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.bitwise_not(gray)
h, w = gray.shape
# 对图像进行开运算,将矩形以外的污点去除
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel, None, None, 5)
# 提取图像最小外接矩形
thresh = cv2.threshold(dst, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
coords = np.column_stack(np.where(thresh > 0))
rect_origin = cv2.minAreaRect(coords)
# 通过最小外接矩形的四个点坐标对图像进行填充
# top bottom left right
if int(rect_origin[0][0]) >= h / 2 and int(rect_origin[0][1]) >= w / 2:
img_modify = cv2.copyMakeBorder(image, 0, h, 0, w, cv2.BORDER_CONSTANT, value=[255, 255, 255])
elif int(rect_origin[0][0]) > h / 2 and int(rect_origin[0][1]) < w / 2:
img_modify = cv2.copyMakeBorder(image, 0, h, w, 0, cv2.BORDER_CONSTANT, value=[255, 255, 255])
elif int(rect_origin[0][0]) < h / 2 and int(rect_origin[0][1]) < w / 2:
img_modify = cv2.copyMakeBorder(image, h, 0, w, 0, cv2.BORDER_CONSTANT, value=[255, 255, 255])
else:
img_modify = cv2.copyMakeBorder(image, h, 0, 0, w, cv2.BORDER_CONSTANT, value=[255, 255, 255])
# 将图像翻转至水平角度
gray_modify = cv2.cvtColor(img_modify, cv2.COLOR_BGR2GRAY)
gray_modify = cv2.bitwise_not(gray_modify)
# 用图像开操作(先腐蚀、后膨胀)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst_modify = cv2.morphologyEx(gray_modify, cv2.MORPH_OPEN, kernel, None, None, 5)
# 旋转图像
thresh = cv2.threshold(dst_modify, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
coords_modify = np.column_stack(np.where(thresh > 0))
angle = cv2.minAreaRect(coords_modify)[-1]
if angle < -45:
angle = -(90 + angle)
else:
angle = -angle
(h_modify, w_modify) = img_modify.shape[:2]
center = (w_modify // 2, h_modify // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
img_rotate = cv2.warpAffine(img_modify, M, (w_modify, h_modify), flags=cv2.INTER_CUBIC,
borderMode=cv2.BORDER_REPLICATE)
# img_rotate = cv2.resize(img_rotate, (1944, 2592))
# 对图像进行裁剪,提取矩形区域
gray_rotate = cv2.cvtColor(img_rotate, cv2.COLOR_BGR2GRAY)
gray_rotate = cv2.bitwise_not(gray_rotate)
# 用图像开操作(先腐蚀、后膨胀)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
gray_rotate = cv2.morphologyEx(gray_rotate, cv2.MORPH_OPEN, kernel, None, None, 3)
thresh = cv2.threshold(gray_rotate, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
coords_rotate = np.column_stack(np.where(thresh > 0))
rect_rotate = cv2.minAreaRect(coords_rotate)
box_rotate = cv2.boxPoints(rect_rotate)
box_rotate = np.int0(box_rotate)
x_min = min([int(box_rotate[0][0]), int(box_rotate[1][0]), int(box_rotate[2][0]), int(box_rotate[3][0])])
y_min = min([int(box_rotate[0][1]), int(box_rotate[1][1]), int(box_rotate[2][1]), int(box_rotate[3][1])])
x_max = max([int(box_rotate[0][0]), int(box_rotate[1][0]), int(box_rotate[2][0]), int(box_rotate[3][0])])
y_max = max([int(box_rotate[0][1]), int(box_rotate[1][1]), int(box_rotate[2][1]), int(box_rotate[3][1])])
img_new = img_rotate[int(x_min):int(x_max), int(y_min):int(y_max)]
cv2.imwrite((img_path + str(bmpFile)), img_new)
print("Crop pictures finished")