You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

矩形图像旋转时同步旋转ROI的技术问题求助

矩形图像旋转时ROI(感兴趣区域)无法同步旋转的问题

我开发了一个图像查看程序,按下上箭头可将图像顺时针旋转90°,按下下箭头可逆时针旋转90°。图像上有一个带蓝色标记的ROI(感兴趣区域),当图像倒置(180度旋转)时ROI能同步旋转,但横向旋转(90°或270°)时,由于矩形图像宽高比反转,rotate_point函数及display_image中的逻辑无法正确实现ROI的同步旋转,特此求助。

程序代码如下:

import os
import cv2
import keyboard
import numpy as np

current_dir = os.getcwd() # Get the current working directory.

rotation_angle = 0 # Rotation angle of the image - initial rotation angle is obviously 0.
engine_img = None # Placeholder for the image.

# Function to rotate a point (x, y) around the image's center (cx, cy) by a given angle.
def rotate_point(cx, cy, x, y, angle):
    angle_rad = np.deg2rad(angle)
    x_rot = (x - cx) * np.cos(angle_rad) - (y - cy) * np.sin(angle_rad) + cx
    y_rot = (x - cx) * np.sin(angle_rad) + (y - cy) * np.cos(angle_rad) + cy
    return int(x_rot), int(y_rot)

def display_image():
    global engine_img

    engine_img = cv2.imread(os.path.join(current_dir, "image.jpg")) # Read the image file - image is a RECTANGLE, not a square.

    if rotation_angle == 0:
        original_width, original_height = engine_img.shape[1], engine_img.shape[0] # Original dimensions when image is in standard position.
        desired_width, desired_height = 920, 690 # Desired dimensions when image is in standard position.

    if rotation_angle == 90 or rotation_angle == -270:
        original_width, original_height = engine_img.shape[0], engine_img.shape[1] # Swap original dimensions, since image has been flipped sideways.
        desired_width, desired_height = 690, 920 # Swap desired dimensions, since image has been flipped sideways.
        engine_img = cv2.rotate(engine_img, cv2.ROTATE_90_CLOCKWISE)

    elif rotation_angle == 180 or rotation_angle == -180:
        original_width, original_height = engine_img.shape[1], engine_img.shape[0] # Image is upside downm, so original dimensions are the same as when in standard position.
        desired_width, desired_height = 920, 690 # Image is upside downm, so desired dimensions are the same as when in standard position.
        engine_img = cv2.rotate(engine_img, cv2.ROTATE_180)

    elif rotation_angle == 270 or rotation_angle == -90:
        original_width, original_height = engine_img.shape[0], engine_img.shape[1] # Swap original dimensions, since image has been flipped sideways.
        desired_width, desired_height = 690, 920 # Swap desired dimensions, since image has been flipped sideways.
        engine_img = cv2.rotate(engine_img, cv2.ROTATE_90_COUNTERCLOCKWISE)

    engine_img = cv2.resize(engine_img, (desired_width, desired_height), interpolation=cv2.INTER_AREA) # Resize the image to desired dimensions.

    image_center_x, image_center_y = int(desired_width / 2), int(desired_height / 2) # Coordinates of point at the center of the image.
    cv2.circle(engine_img, (image_center_x, image_center_y), 5, (0,0,255), 5) # Draw a red circle at the image's center.

    bbox = { # Coordinates of ROI on the image (rectangle).
        "x_min": 2787,
        "y_min": 1385,
        "x_max": 3391,
        "y_max": 1881
    }

    # Adjust coordinates based on the desired image's dimensions.
    x_min = int(bbox.get("x_min", 0) * desired_width / original_width)
    y_min = int(bbox.get("y_min", 0) * desired_height / original_height)
    x_max = int(bbox.get("x_max", 0) * desired_width / original_width)
    y_max = int(bbox.get("y_max", 0) * desired_height / original_height)

    # Function calls to get the position of the ROI after rotation
    x_min_rot, y_min_rot = rotate_point(image_center_x, image_center_y, x_min, y_min, rotation_angle)
    x_max_rot, y_max_rot = rotate_point(image_center_x, image_center_y, x_max, y_max, rotation_angle)

    center_x, center_y = int((x_min_rot + x_max_rot) / 2), int((y_min_rot + y_max_rot) / 2) # Coordinates of point at the center of the ROI on the image.
    cv2.circle(engine_img, (center_x, center_y), 3, (255,0,0), 3) # Draw a blue circle at the ROI's center.

    cv2.namedWindow("Image Viewer", cv2.WINDOW_AUTOSIZE | cv2.WINDOW_GUI_NORMAL) # Open a window.
    cv2.resizeWindow("Image Viewer", engine_img.shape[1], engine_img.shape[0]) # Resize opened window to the image's size.

    cv2.imshow("Image Viewer", engine_img) # Visualize the image on the opened window.

display_image() # Initial call to open the window with the image

while True:
    key = cv2.waitKey(0)
    if key == 27: # Close image window and end program when "ESC" key is pressed.
        break

    if keyboard.is_pressed('up arrow'): # Rotate image 90º clockwise.
        rotation_angle = (rotation_angle + 90) % 360
        display_image()

    if keyboard.is_pressed('down arrow'): # Rotate image 90º counter-clockwise.
        rotation_angle = (rotation_angle - 90) % 360
        display_image()

cv2.destroyAllWindows()

所用图像:
所用图像
需将图像下载至程序同目录并命名为image.jpg。


内容的提问来源于stack exchange,提问作者Matheus Caetano Rocha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:07:33