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

如何在多图场景中退出cv2.setMouseCallback并执行后续代码?

问题:OpenCV鼠标选点满5个后窗口无法正常切换

目标操作

  • 使用cv2.setMouseCallback()通过鼠标点击选择坐标点,每次点击打印坐标
  • 在clickEventCTscanImage和clickEventMRIscanImage两个回调函数中,仅当counter/counterm≤5时记录并打印坐标

期望实现效果

CT图像选满5个点后自动关闭窗口,接着自动打开MRI图像窗口执行相同选点操作;MRI选满5点后关闭窗口,继续执行后续代码。

遇到的问题

  • 在回调函数else分支加return:窗口无法关闭,代码无法继续执行
  • 在回调函数else分支加cv2.destroyAllWindows():CT窗口关闭,但MRI窗口无法打开

代码片段

#importing libraries

import argparse
import numpy as np 
import matplotlib.pyplot as plt
import matplotlib.cm as cm 
import cv2
import imageio
import scipy.ndimage as ndi
import os
from PIL import Image


global CTscanImageCordinates
CTscanImageCordinates = []

global MRIscanImageCordinates
MRIscanImageCordinates = []

counter = 1

# Define Click Function for CT Scan
def clickEventCTscanImage(event, x, y, flags, param):
    global counter

    if event == cv2.EVENT_LBUTTONDOWN:
        if counter <= 5:
            print(x,y)
            CTscanImageCordinates.append([x,y])
            print("hi")
            counter = counter + 1
        else:
            cv2.destroyAllWindows()

counterm = 1

# Define Click Function for MRI Scan
def clickEventMRIscanImage(event, x, y, flags, param):
    global counterm

    if event == cv2.EVENT_LBUTTONDOWN:
        if counterm <= 5:
            print(x,y)
            MRIscanImageCordinates.append([x,y])
            print("hi")
            counterm = counterm + 1
        else:
            cv2.destroyAllWindows()


if __name__ == "__main__":
    arg = argparse.ArgumentParser()
    arg.add_argument("--pathInCTImage", help="Path to CT Scan Image")
    arg.add_argument("--pathInMRIImage", help="Path to MRI Scan Image")
    args = arg.parse_args()

    CTscanImage = cv2.imread(args.pathInCTImage)
    MRIscanImage = cv2.imread(args.pathInMRIImage) #MRI Image will be registered

    cv2.imshow('CT Scan Image', CTscanImage)
    cv2.setMouseCallback('CT Scan Image', clickEventCTscanImage)
    cv2.waitKey()

    cv2.imshow('MRI Scan Image', MRIscanImage)
    cv2.setMouseCallback('MRI Scan Image', clickEventMRIscanImage)
    cv2.waitKey()

已尝试方案

尝试使用return语句和cv2.destroyAllWindows()语句退出图像窗口,均未达到预期效果。


解决方案

问题核心是cv2.waitKey()的阻塞逻辑与回调中窗口销毁的时机不匹配,回调里销毁窗口后主程序仍处于阻塞状态,导致后续代码无法执行。修改逻辑如下:

修改后代码

#importing libraries
import argparse
import numpy as np 
import cv2
import os
from PIL import Image


CTscanImageCordinates = []
MRIscanImageCordinates = []

counter = 1
counterm = 1

# Define Click Function for CT Scan
def clickEventCTscanImage(event, x, y, flags, param):
    global counter
    if event == cv2.EVENT_LBUTTONDOWN and counter <=5:
        print(x,y)
        CTscanImageCordinates.append([x,y])
        counter +=1

# Define Click Function for MRI Scan
def clickEventMRIscanImage(event, x, y, flags, param):
    global counterm
    if event == cv2.EVENT_LBUTTONDOWN and counterm <=5:
        print(x,y)
        MRIscanImageCordinates.append([x,y])
        counterm +=1


if __name__ == "__main__":
    arg = argparse.ArgumentParser()
    arg.add_argument("--pathInCTImage", help="Path to CT Scan Image")
    arg.add_argument("--pathInMRIImage", help="Path to MRI Scan Image")
    args = arg.parse_args()

    CTscanImage = cv2.imread(args.pathInCTImage)
    MRIscanImage = cv2.imread(args.pathInMRIImage)

    # 处理CT图像选点
    cv2.imshow('CT Scan Image', CTscanImage)
    cv2.setMouseCallback('CT Scan Image', clickEventCTscanImage)
    while True:
        key = cv2.waitKey(1) & 0xFF
        # 选满5个点或按ESC退出
        if counter >5 or key ==27:
            cv2.destroyWindow('CT Scan Image')
            break

    # 处理MRI图像选点
    cv2.imshow('MRI Scan Image', MRIscanImage)
    cv2.setMouseCallback('MRI Scan Image', clickEventMRIscanImage)
    while True:
        key = cv2.waitKey(1) & 0xFF
        if counterm >5 or key ==27:
            cv2.destroyWindow('MRI Scan Image')
            break

    # 后续代码可在此执行
    print("CT坐标:", CTscanImageCordinates)
    print("MRI坐标:", MRIscanImageCordinates)

关键修改点

  1. 回调函数仅负责计数和记录坐标,不再处理窗口销毁
  2. 主程序用while循环替代单纯的cv2.waitKey(),主动检查计数是否达标
  3. 满5个点后主动销毁当前窗口并退出循环,确保后续代码正常执行
  4. 保留ESC键退出逻辑,增加交互容错性

内容的提问来源于stack exchange,提问作者Jaskirat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 13:20:32