python+opencv图像处理(提取矩形方框 提取颜色 滤波 轮廓检测 直线检测)

您所在的位置:网站首页 黑色方块图片 python+opencv图像处理(提取矩形方框 提取颜色 滤波 轮廓检测 直线检测)

python+opencv图像处理(提取矩形方框 提取颜色 滤波 轮廓检测 直线检测)

2023-08-28 03:38| 来源: 网络整理| 查看: 265

一、依赖

如果你的python环境没有这些包,则需要安装

pip install numpy \ opencv-python \ pillow 二、使用指南 1、基本信息 近期由于项目需要,需要使用python的opencv库处理图像,在下面的代码中使用了很多cv2的库函数,对这些函数进行了封装,可以直接拷贝调用.项目地址该部分有两个文件构成 main.py 和  replace.py 运行main.py可读取文件夹下的图像,提取图像格子中的字母并保存到本地 2、图像处理流程

原图如下:

提取颜色 HSV特定颜色提取

separate_color_red 提取图像中的红色框线 用HSV提取红色部分,查看HSV颜色分量范围[点击此处] (https://blog.csdn.net/u013270326/article/details/80704754) 参数解释: cv2.inRange(hsv, lowerb=lower_hsv, upperb=high_hsv) 第一个参数为输入图像,图像格式必须转为HSV格式,可通过cv2.cvtColor()转换 第二个参数分别为H,S,V的最低值 第三个参数分别为H,S,V的最高值

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 色彩空间转换为hsv,便于分离 lower_hsv = np.array([0, 43, 46]) # 提取颜色的低值 high_hsv = np.array([10, 255, 255]) # 提取颜色的高值 mask = cv2.inRange(hsv, lowerb=lower_hsv, upperb=high_hsv)

效果如下:

提取颜色 中值滤波

medianBlur 中值滤波,过滤除最外层框线以外的线条 参数解释:cv2.medianBlur(img,19) 第一个参数:输入的图像 第二个参数:滤波模板的尺寸大小,必须是大于1的奇数,如3、5、7

mediu = cv2.medianBlur(img,19)  

效果如下:

中值滤波 HoughLinesP概率霍夫变换直线检测

调用直线检测函数需要先执行边缘检测函数,函数返回二值化图像 参数解释:cv2.Canny(img, 20, 250) 第一个参数:输入图像 第二个参数:阀值1,用于将这些间断的边缘连接起来 第三个参数:阀值2,用于检测图像中明显的边缘 参数解释:cv2.HoughLinesP(img, 1, np.pi / 180, 120, line, minLineLength,maxLineGap) 第一个参数:输入图像,必须为先用Canny边缘检测的图像 第二个参数:直线的半径,建议选1 第三个参数:步长为π/180的角来搜索所有可能的直线 第五个参数:线的最短长度,比这个线短的都会被忽略 第六个参数:两条线之间的最大间隔,如果小于此值,这两条线就会被看成一条线

# 直线检测 img2 = cv2.Canny(img, 20, 250) #边缘检测 line = 4 minLineLength = 50 maxLineGap = 150 # HoughLinesP函数是概率直线检测,注意区分HoughLines函数 lines = cv2.HoughLinesP(img2, 1, np.pi / 180, 120, lines=line, minLineLength=minLineLength,maxLineGap=maxLineGap) lines1 = lines[:, 0, :] # 降维处理 # line 函数勾画直线 # (x1,y1),(x2,y2)坐标位置 # (0,255,0)设置BGR通道颜色 # 2 是设置颜色粗浅度 for x1, y1, x2, y2 in lines1: cv2.line(img, (x1, y1), (x2, y2), (255, 255, 255), 2) findContours轮廓检测

轮廓检测,获取最外层矩形框的偏转角度angle

参数解释:image, contours, hier = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

第一个参数:二值化的图像,可以调用如下函数转为二值化图像

cv2.threshold(cv2.cvtColor(img, 127, 255, cv2.THRESH_BINARY))

第二个参数:表示轮廓的检索模式,有四种: cv2.RETR_EXTERNAL表示只检测外轮廓 cv2.RETR_LIST检测的轮廓不建立等级关系 cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息 cv2.RETR_TREE建立一个等级树结构的轮廓。 第三个参数:cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1 cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标. 下面的代码对检测到的轮廓进行了筛选.并返回轮廓矩形坐标或倾斜角度

#检测轮廓 # ret, thresh = cv2.threshold(cv2.cvtColor(img, 127, 255, cv2.THRESH_BINARY)) image, contours, hier = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for c in contours: #遍历轮廓 rect = cv2.minAreaRect(c) #生成最小外接矩形 box_ = cv2.boxPoints(rect) h = abs(box_[3, 1] - box_[1, 1]) w = abs(box_[3, 0] - box_[1, 0]) print("宽,高",w,h) #只保留需要的轮廓 if (h > 3000 or w > 2200): continue if (h < 2500 or w < 1500): continue box = cv2.boxPoints(rect) # 计算最小面积矩形的坐标 box = np.int0(box) # 将坐标规范化为整数 angle = rect[2] #获取矩形相对于水平面的角度 if angle > 0: if abs(angle) > 45: angle = 90 - abs(angle) else: if abs(angle) > 45: angle = (90 - abs(angle)) # 绘制矩形 # cv2.drawContours(img, [box], 0, (255, 0, 255), 3) print("轮廓数量", len(contours)) rotate 旋转图像至水平方向

参数解释:cv2.getRotationMatrix2D(center, angle, 1) 第一个参数:旋转图像的基点,这里同过获取图像的宽高计算中心点 第二个参数:旋转角度 第三个参数:图像缩放因子 参数解释:cv2.warpAffine(img, img_ratete, (w, h)) 第一个参数:原图像 第二个参数:从getRotationMatrix2D得到的图像 第三个参数:图像大小

(h, w) = img.shape[:2] #获得图片高,宽 center = (w // 2, h // 2) #获得图片中心点 img_ratete = cv2.getRotationMatrix2D(center, angle, 1) rotated = cv2.warpAffine(img, img_ratete, (w, h))

效果如下:

中值滤波 cut1 通过图像坐标从外层矩形框处裁剪原图 沿边框裁剪 裁剪图片 裁剪图片可通过数组切片操作完成,进行此操作打开图像必须用cv2.imiread(“path”)加载图像 img[y1:y2, x1:x2] #切片裁剪图像

效果如图:

沿方格裁剪 replace 消除多余红色框线 如下代码可实现特定像素的替换,这个把红色替换为白色,进行此操作打开图像必须用PIL库函数Image.open(“path”)加载图像 img2 = Image.open(path3) img2 = img2.convert('RGBA') # 图像格式转为RGBA pixdata = img2.load() for y in range(img2.size[1]): for x in range(img2.size[0]): if pixdata[x, y][0] > 220: # 红色像素 pixdata[x, y] = (255, 255, 255, 255) # 替换为白色,参数分别为(R,G,B,透明度) img2 = img2.convert('RGB') # 图像格式转为RGB print("替换文件",pathd) img2.save(path3)

效果如图:

消除多余框线 3、完整代码 #main.py import cv2 import numpy as np import os import replace def separate_color_red(img): #颜色提取 # gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 色彩空间转换为hsv,便于分离 lower_hsv = np.array([0, 43, 46]) # 提取颜色的低值 high_hsv = np.array([10, 255, 255]) # 提取颜色的高值 mask = cv2.inRange(hsv, lowerb=lower_hsv, upperb=high_hsv) print("颜色提取完成") return mask def salt(img, n): #椒盐去燥 for k in range(n): i = int(np.random.random() * img.shape[1]) j = int(np.random.random() * img.shape[0]) if img.ndim == 2: img[j, i] = 255 elif img.ndim == 3: img[j, i, 0] = 255 img[j, i, 1] = 255 img[j, i, 2] = 255 print("去燥完成") return img def show(name, img): #显示图片 cv2.namedWindow(str(name), cv2.WINDOW_NORMAL) cv2.resizeWindow(str(name), 800, 2000) # 改变窗口大小 cv2.imshow(str(name), img) def lines(img): # 直线检测 img2 = cv2.Canny(img, 20, 250) #边缘检测 line = 4 minLineLength = 50 maxLineGap = 150 # HoughLinesP函数是概率直线检测,注意区分HoughLines函数 lines = cv2.HoughLinesP(img2, 1, np.pi / 180, 120, lines=line, minLineLength=minLineLength,maxLineGap=maxLineGap) lines1 = lines[:, 0, :] # 降维处理 # line 函数勾画直线 # (x1,y1),(x2,y2)坐标位置 # (0,255,0)设置BGR通道颜色 # 2 是设置颜色粗浅度 for x1, y1, x2, y2 in lines1: cv2.line(img, (x1, y1), (x2, y2), (255, 255, 255), 2) return img def contour(img): #检测轮廓 # ret, thresh = cv2.threshold(cv2.cvtColor(img, 127, 255, cv2.THRESH_BINARY)) image, contours, hier = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for c in contours: #遍历轮廓 rect = cv2.minAreaRect(c) #生成最小外接矩形 box_ = cv2.boxPoints(rect) h = abs(box_[3, 1] - box_[1, 1]) w = abs(box_[3, 0] - box_[1, 0]) print("宽,高",w,h) #只保留需要的轮廓 if (h > 3000 or w > 2200): continue if (h < 2500 or w < 1500): continue box = cv2.boxPoints(rect) # 计算最小面积矩形的坐标 box = np.int0(box) # 将坐标规范化为整数 angle = rect[2] #获取矩形相对于水平面的角度 if angle > 0: if abs(angle) > 45: angle = 90 - abs(angle) else: if abs(angle) > 45: angle = (90 - abs(angle)) # 绘制矩形 # cv2.drawContours(img, [box], 0, (255, 0, 255), 3) print("轮廓数量", len(contours)) return img, box, angle def rotate(img, angle): #旋转图片 (h, w) = img.shape[:2] #获得图片高,宽 center = (w // 2, h // 2) #获得图片中心点 img_ratete = cv2.getRotationMatrix2D(center, angle, 1) rotated = cv2.warpAffine(img, img_ratete, (w, h)) return rotated def cut1(img, box): #从轮廓出裁剪图片 x1, y1 = box[1] #获取左上角坐标 x2, y2 = box[3] #获取右下角坐标 img_cut = img[y1+10:y2-10, x1+10:x2-10] #切片裁剪图像 return img_cut def cut2(img, out_path, filed): #裁剪方格中图像并保存 #@config i_:i为裁剪图像的y坐标区域, j_:j为裁剪图像的x坐标区域 if not os.path.isdir(out_path): #创建文件夹 os.makedirs(out_path) h, w, _ = img.shape #获取图像通道 print(h, w) s,i_ = 0,0 #循环保存图像 for i in range(h//12,h,h//12): j_ = 0 for j in range(w//8,w,w//8): imgd = img[i_ + 5:i - 5, j_ + 5:j - 5] # img_list.append(img[i_+10:i-10,j_+10:j-10]) out_pathd = out_path+filed[:-4]+"_"+str(s)+".jpg" #图像保存路径 cv2.imwrite(out_pathd,imgd) print("保存文件",out_pathd) s += 1 j_ = j i_ = i if __name__ == "__main__": path = "/home/crxm/C1/" #读取图像文件夹 put_path = "/home/crxm/C2/" #保存图像文件夹 for file in os.listdir(path): #遍历访问图像 pathd = path + file + "/" out_path = put_path + file + "/" for filed in os.listdir(pathd): img_path = (pathd + filed) img = cv2.imread(img_path) #读取图像 img_separate = separate_color_red(img) #提取红色框先 mediu = cv2.medianBlur(img_separate,19) #中值滤波,过滤除最外层框线以外的线条 img_lines = lines(mediu) #直线检测,补充矩形框线 img_contours,box,angle = contour(img_lines) #轮廓检测,获取最外层矩形框的偏转角度 print("角度",angle,"坐标",box) img_rotate = rotate(img_lines,angle) #旋转图像至水平方向 img_contours,box, _ = contour(img_rotate) #获取水平矩形框的坐标 img_original_rotate = rotate(img,angle) #旋转原图至水平方向 img_original_cut = cut1(img_original_rotate,box) #通过图像坐标从外层矩形框处裁剪原图 cut2(img_original_cut,out_path,filed) #裁剪方格保存 replace.replace(put_path) #消除多余红色框线 # show("img",img) # show("img_separate", img_separate) # show("mediu", mediu) # show("img_lines", img_lines) # show("img_contours", img_contours) # show("img__rotate",img_rotate) # show("img_original_cut",img_original_cut) cv2.waitKey(0) cv2.destroyAllWindows() #replace.py from PIL import Image import os def replace(img_path): for path in os.listdir(img_path): path2 = img_path + path + "/" for pathd in os.listdir(path2): path3 = path2 + pathd img2 = Image.open(path3) img2 = img2.convert('RGBA') # 图像格式转为RGBA pixdata = img2.load() for y in range(img2.size[1]): for x in range(img2.size[0]): if pixdata[x, y][0] > 220: # 红色像素 pixdata[x, y] = (255, 255, 255, 255) # 替换为白色,参数分别为(R,G,B,透明度) img2 = img2.convert('RGB') # 图像格式转为RGB print("替换文件",pathd) img2.save(path3) #红色像素替换为白色


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3