如何在多图场景中退出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)
关键修改点
- 回调函数仅负责计数和记录坐标,不再处理窗口销毁
- 主程序用
while循环替代单纯的cv2.waitKey(),主动检查计数是否达标 - 满5个点后主动销毁当前窗口并退出循环,确保后续代码正常执行
- 保留ESC键退出逻辑,增加交互容错性
内容的提问来源于stack exchange,提问作者Jaskirat
相关产品推荐
相关产品推荐

