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-18
193

10-05
723
