真的!只需 “六步” 实现图像特定物体识别!!!( 三 )


def get_contours(eroded_iamge):"""获取光伏组件串图片的轮廓并在原始图像上绘制轮廓输入为形态学处理后的二值图像,黑色为背景,白色为目标cv2.RETR_EXTERNAL 只检测外轮廓cv2.CHAIN_APPROX_SIMPLE"""# contours是轮廓本身,hierarchy 每条轮廓对应的属性(后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号)contours, hierarchy = cv2.findContours(eroded_iamge, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 获取组件区域轮廓return contours
6、切割并保存区域图片
最后一步,根据轮廓数据在原始图片上进行区域切割并将切割后图片保存至磁盘,实现函数如下,传入轮廓区域与原始图片,返回轮廓处理的数量 。
def get_and_save_areas(contours, original_image):"""在原始图片中切割并保存轮廓区域"""min_area = 300# 过滤那些小面积的噪音区域 index = 0# 用来标识组件区域的数量for numcontours, contour in enumerate(contours):iamge_area = cv2.contourArea(contour)if iamge_area > min_area:x, y, w, h = cv2.boundingRect(contour)module_image = original_image[y:y + h, x: x + w]index = index + 1cv2.imwrite('Output/' + str(x) + '_' + str(y) + '_' + str(w) + '_' + str(h) + '_' + str(iamge_area) + '_' + str(index) + '.jpg', module_image)# 文件名以坐标(X、Y),图片的高度与宽度,图片面积,文件序号return index
全部完整代码如下:
为了方便阅读与整理思路,将每个处理步骤封装为一个函数,并使用一个总函数来组合每个处理步骤 。
import cv2import numpy as npdef read_resize_image(path, size=1.0):"""读取原始图片文件并从新设置大小1) 使用imread读取文件2)使用resize从新设置文件大小3) 函数返回的是图片的原始数据,可理解为一个三维数组,每个维度分别表示长、宽、通道数,数组中的值表示图片每个像素点不同通道的取值"""original_image = cv2.imread(path)if size != 1.0:height, width = original_image.shape[:2]size = (int(width * size), int(height * size))original_image = cv2.resize(original_image, size, interpolation=cv2.INTER_AREA)# print(original_image)# print(original_image.shape)return original_imagedef get_hsv_image(original_image):"""获取hsv色彩空间图片1) 先将BGR色彩转化为HSV色彩"""hsv_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2HSV)# 将BGR色彩转化为HSV色彩cv2.imshow("HSV Image", hsv_image)print(hsv_image.shape)return hsv_imagedef get_mask_image(hsv_image, lower, upper):"""获取二值化图片1)通过阀值获取二值化图像"""mask_image = cv2.inRange(hsv_image, lower, upper)# 获取二值化图片cv2.imshow("Mask Image", mask_image)print(mask_image)print(mask_image.shape)return mask_imagedef get_morphology_image(mask_image):"""对二值化图像进行形态学处理-消除噪音影响1) 先进行膨胀处理膨胀就是使用算法,来将图像的边缘扩大些 。作用就是将目标的边缘或者是内部的坑填掉,去掉较小的孔洞2) 再进行腐蚀处理腐蚀:腐蚀会把物体的边界腐蚀掉,主要应用在去除白噪声,也可以断开连在一起的物体"""kernel = np.ones((5, 5), np.uint8)dialationIamge = cv2.dilate(mask_image, kernel, iterations=1)# 膨胀处理eroded_iamge = cv2.erode(dialationIamge, kernel, iterations=1)# 腐蚀处理cv2.imshow("Eroded Iamge ", eroded_iamge)# 显示形态学处理过后的图片return eroded_iamgedef get_contours(eroded_iamge):"""获取光伏组件串图片的轮廓并在原始图像上绘制轮廓输入为形态学处理后的二值图像,黑色为背景,白色为目标cv2.RETR_EXTERNAL 只检测外轮廓cv2.CHAIN_APPROX_SIMPLE"""# contours是轮廓本身,hierarchy 每条轮廓对应的属性(后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号)contours, hierarchy = cv2.findContours(eroded_iamge, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 获取组件区域轮廓return contoursdef get_and_save_areas(contours, original_image):"""在原始图片中切割并保存轮廓区域"""min_area = 300# 过滤那些小面积的噪音区域index = 0# 用来标识组件区域的数量for numcontours, contour in enumerate(contours):iamge_area = cv2.contourArea(contour)if iamge_area > min_area:x, y, w, h = cv2.boundingRect(contour)module_image = original_image[y:y + h, x: x + w]index = index + 1cv2.imwrite('Output/' + str(x) + '_' + str(y) + '_' + str(w) + '_' + str(h) + '_' + str(iamge_area) + '_' + str(index) + '.jpg', module_image)# 文件名以坐标(X、Y),图片的高度与宽度,图片面积,文件序号return indexdef execute():"""组合执行每个一个处理步骤"""path = 'Images/DJI_0537.jpg'original_image = read_resize_image(path, 0.3)# 原始图像为3000X40000为方便观察,先将图片缩小5倍 既0.2hsv_image = get_hsv_image(original_image)# 将rgb原始图像转化为hsv图像lower = np.array([44, 57, 130])upper = np.array([120, 191, 249])mask_image = get_mask_image(hsv_image, lower, upper)# 获取二值化图像 通过HSV的高低阈值,提取图像部分区域eroded_iamge = get_morphology_image(mask_image)# 对二值化的图像进行形态学处理contours = get_contours(eroded_iamge)# 获取光伏组件轮廓区域get_and_save_areas(contours, original_image)# 将获取的轮廓区域截取图片并保存到文件cv2.drawContours(original_image, contours, -1, (0, 0, 255), 1)# 在原图上绘制轮廓cv2.imshow("Original Image", original_image)# 显示原始带轮廓图像execute()# 执行入口函数while True:cv2.waitKey(1)