鼠标点击根据蒙版画任意图像ROI,并生成二值图像

import cv2
import numpy as np

# Initialize global variables
drawing = False  # True if the mouse is pressed
mode = 'rectangle'  # 'rectangle', 'circle', 'ellipse', or 'freehand'
ix, iy = -1, -1  # Initial position
rois = []  # List to store drawn ROIs
selected_roi_index = -1  # Index of the selected ROI for dragging
resizing = False  # True if resizing an ROI
points = []  # List to store points for freehand drawing


# Mouse callback function
def draw_shape(event, x, y, flags, param):
    global ix, iy, drawing, mode, points

    if event == cv2.EVENT_LBUTTONDOWN:
        if mode == 'freehand':
            drawing = True
            ix, iy = x, y
            points.append((x, y))
        else:
            drawing = True
            ix, iy = x, y

    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing:
            if mode == 'freehand':
                points.append((x, y))
                temp_image = cv2.cvtColor(image_np.copy(), cv2.COLOR_GRAY2BGR)
                draw_current_roi(temp_image, x, y)
                draw_all_rois(temp_image)
                cv2.imshow('image', temp_image)
            else:
                temp_image = cv2.cvtColor(image_np.copy(), cv2.COLOR_GRAY2BGR)
                draw_current_roi(temp_image, x, y)
                draw_all_rois(temp_image)
                cv2.imshow('image', temp_image)

    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        if mode == 'freehand':
            points.append((x, y))
            add_roi('freehand', points)
            points = []
        else:
            add_roi(mode, (ix, iy), (x, y))
        update_output_image()
        display_final_image()


def draw_current_roi(image, x, y):
    if mode == 'rectangle':
        cv2.rectangle(image, (ix, iy), (x, y), (0, 0, 255), 1)  # Red color for rectangles
    elif mode == 'circle':
        radius = int(((x - ix) ** 2 + (y - iy) ** 2) ** 0.5)
        cv2.circle(image, (ix, iy), radius, (0, 0, 255), 1)  # Red color for circles
    elif mode == 'ellipse':
        cv2.ellipse(image, ((ix + x) // 2, (iy + y) // 2), (abs(x - ix) // 2, abs(y - iy) // 2), 0, 0, 360,
                    (0, 0, 255), 1)  # Red color for ellipses


def draw_all_rois(image):
    for roi in rois:
        if roi[0] == 'rectangle':
            cv2.rectangle(image, roi[1], roi[2], (0, 0, 255), 1)
        elif roi[0] == 'circle':
            cv2.circle(image, roi[1], int(roi[2]), (0, 0, 255), 1)
        elif roi[0] == 'ellipse':
            cv2.ellipse(image, roi[1], roi[2], roi[3], 0, 360, (0, 0, 255), 1)
        elif roi[0] == 'freehand':
            cv2.polylines(image, [np.array(roi[1])], False, (0, 0, 255), 1)


def add_roi(roi_type, *args):
    if roi_type == 'rectangle':
        roi = (roi_type, args[0], args[1])
    elif roi_type == 'circle':
        center = args[0]
        edge = args[1]
        radius = int(((edge[0] - center[0]) ** 2 + (edge[1] - center[1]) ** 2) ** 0.5)
        roi = (roi_type, center, radius)
    elif roi_type == 'ellipse':
        roi = (roi_type, args[0], args[1], args[2])
    elif roi_type == 'freehand':
        roi = (roi_type, args[0])
    rois.append(roi)


def update_output_image():
    global output_image
    output_image[:] = np.zeros_like(image_np)
    for roi in rois:
        if roi[0] == 'rectangle':
            cv2.rectangle(output_image, roi[1], roi[2], 255, -1)
        elif roi[0] == 'circle':
            cv2.circle(output_image, roi[1], roi[2], 255, -1)
        elif roi[0] == 'ellipse':
            cv2.ellipse(output_image, roi[1], roi[2], roi[3], 0, 360, 255, -1)
        elif roi[0] == 'freehand':
            cv2.fillPoly(output_image, [np.array(roi[1])], 255)


def display_final_image():
    display_image = cv2.cvtColor(image_np.copy(), cv2.COLOR_GRAY2BGR)
    draw_all_rois(display_image)
    cv2.imshow('image', display_image)


# Load the original image as grayscale
image_path = '*.bmp'  # Replace with your image path
image_np = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

# Create an all-black mask with the same size as the original image
output_image = np.zeros_like(image_np)

# Create a window and set a mouse callback
cv2.namedWindow('image', cv2.WINDOW_NORMAL)  # Create a resizable window
cv2.resizeWindow('image', image_np.shape[1], image_np.shape[0])  # Resize window to fit the image
cv2.setMouseCallback('image', draw_shape)

print("Press 'r' to switch to rectangle mode.")
print("Press 'c' to switch to circle mode.")
print("Press 'e' to switch to ellipse mode.")
print("Press 'f' to switch to freehand mode.")
print("Press 'q' to quit.")

# Display the original image
cv2.imshow('image', image_np)

while True:
    key = cv2.waitKey(1) & 0xFF

    if key == ord('q'):
        break
    elif key == ord('r'):
        mode = 'rectangle'
    elif key == ord('c'):
        mode = 'circle'
    elif key == ord('e'):
        mode = 'ellipse'
    elif key == ord('f'):
        mode = 'freehand'

# Save the final mask as a grayscale single-channel image
mask_filename = 'output_mask.png'
cv2.imwrite(mask_filename, output_image)

# Cleanup
cv2.destroyAllWindows()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值