根据mask绘制contour ,bounding box。批量展示图片 等工具函数

根据mask绘制contour

import cv2
import numpy as np
import SimpleITK as sitk


dcm_file = r'G:\data\3Dircadb\3Dircadb1.3\PATIENT_DICOM\image_137'
dcm_liver = r'G:\data\3Dircadb\3Dircadb1.3\MASKS_DICOM\liver\image_137'
dcm_tumor = r'G:\data\3Dircadb\3Dircadb1.3\MASKS_DICOM\livertumor\image_137'


def drawContour():

    image = sitk.ReadImage(dcm_file)
    image_array = sitk.GetArrayFromImage(image)
    image_array = np.squeeze(image_array)
    image_array = image_array.astype(np.float32)
	# windowing 操作
    # min:-200, max:200
    # img = (img-min)/(max - min)
    image_array = (image_array - (-200)) / 400.0
    image_array[image_array > 1] = 1.0
    image_array[image_array < 0] = 0.0
    # 不必须转化为0-255

    # 若不转化为彩色,那么最后画出来的contour也只能是灰度的
    image_array = cv2.cvtColor(image_array, cv2.COLOR_GRAY2BGR)

    liver = sitk.ReadImage(dcm_liver)
    liver_array = sitk.GetArrayFromImage(liver)
    liver_array = np.squeeze(liver_array)
    # liver_array *= 255 不必须

    tumor = sitk.ReadImage(dcm_tumor)
    tumor_array = sitk.GetArrayFromImage(tumor)
    tumor_array = np.squeeze(tumor_array)
    # tumor_array *= 255 不必须

    # findContours 必须目标是white,背景是black (0,1 和 0,255 都可以)
    # py3 只返回2个参数,而非之前的3个
    contours, hierarchy = cv2.findContours(
        liver_array, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    contours2, hierarchy2 = cv2.findContours(
        tumor_array, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    cnt = contours[0]
    # drawContours 直接改变原图
    # 第三个参数 index
    # 第四个参数color: BGR
    # 两种不同的方式指明画哪个contour
    cv2.drawContours(image_array, [cnt], 0, (0, 0, 255), 1)
    cv2.drawContours(image_array, contours2, -1,
                     (255, 0, 0
''' #!/usr/bin/python3 # -*- coding: utf-8 -*- # @团队 : Safhels # @时间 : 2024/4/9 0009 11:34 # @作者 : 林鹏程 # @文件名: page_auto_set_4_1.py # @软件: PyCharm ''' import cv2 import numpy as np def is_point_in_polygon(mask, center): # 确保 mask 是整型数组 mask_one = np.array(mask[0], dtype=np.int32) # 计算maskBounding Box,提前判断是否在框内 x_min, y_min = np.min(mask_one, axis=0) x_max, y_max = np.max(mask_one, axis=0) # 进行简单的边界判断 if not (x_min <= center[0] <= x_max and y_min <= center[1] <= y_max): return False # 判断点是否在第一个区域内 in_first_region = cv2.pointPolygonTest(mask_one, center, False) >= 0 if len(mask) == 1: return in_first_region # 如果有多个区域,检查是否在其他区域内 for region in mask[1:]: other_mask = np.array(region, dtype=np.int32) if cv2.pointPolygonTest(other_mask, center, False) >= 0: return False return in_first_region def calculate_distance(point1, point2): return np.sqrt((point1[0] - point2[0])**2 + (point1[1] - point2[1])**2) def image_detect(frame,config_area_current,currentback,kernal_erode,kernal_dilate,kernal_erode_2,min_area,max_area,adjust_threshold): # 图像播放 feature = 3 # 选择要检测的特征,1表示检测中心点,3表示三点检测 mean_value = 0 number_detect = 0 frame_dec = frame.copy() # 创建与原始图像相同大小的空白掩模 mask_roi = np.zeros_like(frame[:, :, 0], dtype=np.uint8) config_area = list(config_area_current.values()) for mask_pts in config_area: for mask in mask_pts: if len(mask) == 1: cv2.fillPoly(mask_roi, np.array([mask[0]], dtype=np.int32), 255) else: cv2.fillPoly(mask_roi, np.array([mask[0]], dtype=np.int32),255) cv2.fillPoly(mask_roi, np.array(mask[1:], dtype=np.int32), 0) frame_gray = cv2.cvtColor(frame_dec, cv2.COLOR_BGR2GRAY) frame_threshold = cv2.threshold(frame_gray,adjust_threshold, 255, cv2.THRESH_BINARY)[1] if currentback == 0: # 检测亮度低于背景的阈值 frame_threshold = cv2.threshold(frame_gray, adjust_threshold, 255, cv2.THRESH_BINARY_INV)[1] frame_threshold = cv2.bitwise_and(frame_threshold, mask_roi) # 对图像进行腐蚀和膨胀 kernel_erode_init = np.ones((3, 3), np.uint8) frame_threshold = cv2.erode(frame_threshold, kernel_erode_init,iterations=kernal_erode) frame_threshold = cv2.dilate(frame_threshold, kernel_erode_init,iterations=kernal_dilate) frame_threshold = cv2.erode(frame_threshold, kernel_erode_init,iterations=kernal_erode_2) # 寻找轮廓 contours, _ = cv2.findContours(frame_threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contours_news = [[] for i in range(len(config_area))] contours_news_area = [[0] for i in range(len(config_area))] center_all = [[] for i in range(len(config_area))] #计算分析区 for contour in contours: # 找到最大轮廓的凸包 M_cur = cv2.moments(contour) area = cv2.contourArea(contour) if area >= min_area and area <= max_area: if M_cur["m00"] != 0: cx = int(M_cur["m10"] / M_cur["m00"]) cy = int(M_cur["m01"] / M_cur["m00"]) center = (cx, cy) else: # 质心计算失败的情况 center = (0, 0) for area_current in config_area: for mask in area_current: flag = is_point_in_polygon(mask, center) if flag == True: contours_news[config_area.index(area_current)].append(contour) contours_news_area[config_area.index(area_current)].append(area) center_all[config_area.index(area_current)].append(center) contours_max = [max(contours_news_area[i]) for i in range(len(config_area))] for cc in range(len(contours_news)): if len(contours_news[cc]) >0: for kk in range(len(contours_news[cc])): contour = contours_news[cc][kk] area = cv2.contourArea(contour) if area >= min_area and area <= max_area : # 绘制轮廓 if area == contours_max[cc]: cv2.drawContours(frame_dec, [contour], -1, (0, 255, 255), thickness=cv2.FILLED) # 找到最大轮廓的凸包 hull = cv2.convexHull(contour) M = cv2.moments(contour) if M['m00'] != 0: center = (int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])) else: center = (0, 0) cv2.circle(frame_dec, (int(center[0]), int(center[1])), 2, (0, 0, 255), thickness=cv2.FILLED) number_detect +=1 mean_value += area if feature == 3: # 计算凸包上每两个点之间的距离 distances = [] for i in range(len(hull)): for j in range(i + 1, len(hull)): distance = np.linalg.norm(hull[i] - hull[j]) distances.append((i, j, distance)) # 找到距离最长的两个点 longest_distance = max(distances, key=lambda x: x[2]) point1_index, point2_index, max_distance = longest_distance # 获取最长距离的两个点 point1 = tuple(hull[point1_index][0]) point2 = tuple(hull[point2_index][0]) if calculate_distance(point1, center) > calculate_distance(point2, center): head_point = point1 tail_point = point2 else: head_point = point2 tail_point = point1 head_around_point, tail_around_point = [], [] hull = cv2.convexHull(contour, returnPoints=False) for i in range(len(hull)): idx = hull[i][0] if tuple(contour[idx][0]) == head_point: p1 = idx - 1 if idx > 0 else len(contour) - 1 p2 = idx + 1 if idx < len(contour) - 1 else 0 head_around_point.append(tuple(contour[p1][0])) head_around_point.append(tuple(contour[p2][0])) if tuple(contour[idx][0]) == tail_point: p1 = idx - 1 if idx > 0 else len(contour) - 1 p2 = idx + 1 if idx < len(contour) - 1 else 0 tail_around_point.append(tuple(contour[p1][0])) tail_around_point.append(tuple(contour[p2][0])) cv2.circle(frame_dec, (int(head_point[0]), int(head_point[1])), 2, (255, 0, 255), thickness=cv2.FILLED) cv2.putText(frame_dec, "h", (int(head_point[0]), int(head_point[1])), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1) cv2.circle(frame_dec, (int(tail_point[0]), int(tail_point[1])), 2, (255, 0, 0), thickness=cv2.FILLED) cv2.putText(frame_dec, "t", (int(tail_point[0]), int(tail_point[1])), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1) cv2.line(frame_dec, (int(head_point[0]), int(head_point[1])), (int(center[0]), int(center[1])), (255, 0, 0), thickness=1) for point in head_around_point: rever_point_x = point[0] rever_point_y = point[1] if (head_point[0] - point[0]) == 0: rever_point_x = head_point[0] rever_point_y = head_point[1] - 12 * ((point[1] - head_point[1]) / abs(point[1] - head_point[1])) else: rate = (head_point[1] - point[1]) / (head_point[0] - point[0]) if head_point[0] - point[0] < 0: rever_point_x = head_point[0] - (144 / (rate ** 2 + 1)) ** 0.5 else: rever_point_x = head_point[0] + (144 / (rate ** 2 + 1)) ** 0.5 rever_point_y = head_point[1] + rate * (rever_point_x - head_point[0]) point = (int(rever_point_x), int(rever_point_y)) cv2.line(frame_dec, (int(head_point[0]), int(head_point[1])), point, (0, 255, 0), thickness=1) else: cv2.drawContours(frame_dec, [contour], -1, (0, 65, 255), thickness=cv2.FILLED) if number_detect != len(config_area_current): cv2.putText(frame_dec, "warning some area project error", (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) if number_detect !=0: mean_value = int(mean_value / number_detect) return frame_dec,mean_value 以上是后端算法部分,根据上述修改,完善算法部分
07-31
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值