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

OpenCV中[WARN:0]终止异步回调错误排查求助

解决OpenCV [WARN:0] terminating async callback 警告问题

我之前在Windows上做OpenCV摄像头项目时也踩过这个坑,这个警告本质是摄像头资源释放不彻底,异步回调线程还在后台运行就被强制终止导致的。你已经尝试了camera.release()和cv2.destroyAllWindows(),但问题出在这些操作的位置和覆盖范围不对,结合你的代码,给你几个具体的修复方案:

核心问题分析

你的代码里存在两个关键疏漏:

  • 正常退出循环后(按ESC),只关闭了socket,完全没处理摄像头资源释放和窗口销毁
  • 异常捕获块里也没清理摄像头资源,一旦程序抛出异常,摄像头资源会残留,触发异步回调警告

修复方案

1. 用finally块统一管理资源释放

把所有资源清理逻辑放在finally块里,不管程序是正常退出还是抛出异常,都会执行资源清理,避免残留。

2. 给Windows摄像头指定CAP_DSHOW后端

Windows上默认的摄像头后端存在异步回调兼容性问题,显式指定CAP_DSHOW可以直接规避很多这类警告。

修改后的完整代码

import cv2
import socket
import numpy as np
import math
import time

# 提前初始化全局变量,避免finally块报错
state1 = "off"
state2 = "off"
state3 = "off"
mode = "on"
host = "192.168.0.106" 
port = 9345
mySocket = None
cap = None

try:
    start_time = time.time()
    mySocket = socket.socket()
    mySocket.connect((host,port))
    # 显式指定Windows摄像头后端,解决异步回调问题
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
    
    while(cap.isOpened()):
        ret, img = cap.read()
        if not ret:  # 增加判断,防止摄像头读取失败导致后续报错
            break
            
        cv2.rectangle(img, (300,300), (100,100), (0,255,0),0)
        crop_img = img[100:300, 100:300]
        
        grey = cv2.cvtColor(crop_img, cv2.COLOR_BGR2GRAY)
        value = (35, 35)
        blurred = cv2.GaussianBlur(grey, value, 0)
        _, thresh1 = cv2.threshold(blurred, 127, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
        cv2.imshow('Thresholded', thresh1)
        
        (version, _, _) = cv2.__version__.split('.')
        if version == '3':
            image, contours, hierarchy = cv2.findContours(thresh1.copy(), \
                cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
        elif version == '2':
            contours, hierarchy = cv2.findContours(thresh1.copy(),cv2.RETR_TREE, \
                cv2.CHAIN_APPROX_NONE)
        
        cnt = max(contours, key = lambda x: cv2.contourArea(x))
        x, y, w, h = cv2.boundingRect(cnt)
        cv2.rectangle(crop_img, (x, y), (x+w, y+h), (0, 0, 255), 0)
        
        hull = cv2.convexHull(cnt)
        drawing = np.zeros(crop_img.shape,np.uint8)
        cv2.drawContours(drawing, [cnt], 0, (0, 255, 0), 0)
        cv2.drawContours(drawing, [hull], 0,(0, 0, 255), 0)
        
        hull = cv2.convexHull(cnt, returnPoints=False)
        defects = cv2.convexityDefects(cnt, hull)
        count_defects = 0
        cv2.drawContours(thresh1, contours, -1, (0, 255, 0), 3)
        
        # 增加判断,避免没有检测到手势缺陷时报错
        if defects is not None:
            for i in range(defects.shape[0]):
                s,e,f,d = defects[i,0]
                start = tuple(cnt[s][0])
                end = tuple(cnt[e][0])
                far = tuple(cnt[f][0])
                
                a = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2)
                b = math.sqrt((far[0] - start[0])**2 + (far[1] - start[1])**2)
                c = math.sqrt((end[0] - far[0])**2 + (end[1] - far[1])**2)
                
                angle = math.acos((b**2 + c**2 - a**2)/(2*b*c)) * 57
                if angle <= 90:
                    count_defects += 1
                    cv2.circle(crop_img, far, 1, [0,0,255], -1)
                cv2.line(crop_img,start, end, [0,255,0], 2)
        
        # 手势控制逻辑保持不变
        if count_defects == 1:
            if (time.time()>start_time+2):
                if mode == "on":
                    mySocket.send("on_led1".encode())
                    state1 = "on"
                    print("led 1 is on")
                else:
                    mySocket.send("off_led1".encode())
                    state1 = "off"
                    print("led 1 is off")
                start_time = time.time()
            cv2.putText(img, "led 1 is "+state1, (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, 2)
        elif count_defects == 2:
            if (time.time()>start_time+2):
                if mode == "on":
                    mySocket.send("on_led2".encode())
                    state2 = "on"
                    print("led 2 is on")
                else:
                    mySocket.send("off_led2".encode())
                    state2 = "off"
                    print("led 2 is off")
                start_time = time.time()
            cv2.putText(img, "led 2 is "+state2, (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, 2)
        elif count_defects == 3:
            if (time.time()>start_time+2):
                if mode == "on":
                    mySocket.send("on_led3".encode())
                    state3 = "on"
                    print("led 3 is on")
                else:
                    mySocket.send("off_led3".encode())
                    state3 = "off"
                    print("led 3 is off")
                start_time = time.time()
            cv2.putText(img, "led 3 is "+state3, (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, 2)
        elif count_defects == 4:
            cv2.putText(img,"mode is "+mode, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)
            if(time.time() > start_time+2):
                mode = "off" if mode == "on" else "on"
                start_time = time.time()
                print(mode)
        else:
            cv2.putText(img, "use your fingure for turn On/Off lights current mode is "+mode, (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, 2)
        
        cv2.imshow('Gesture', img)
        all_img = np.hstack((drawing, crop_img))
        cv2.imshow('Contours', all_img)
        
        k = cv2.waitKey(10)
        if k == 27:
            break
except Exception as e:
    print(f"程序运行出错: {e}")
    if mySocket:
        try:
            mySocket.send("close_all".encode())
        except:
            pass
finally:
    # 统一释放所有资源,不管正常退出还是异常
    if mySocket:
        mySocket.close()
    if cap:
        cap.release()
    cv2.destroyAllWindows()
    cv2.waitKey(1)  # Windows上额外加这句,确保窗口彻底销毁

关键修改点说明

  • finally块统一清理:确保所有路径下都会释放摄像头、关闭socket和销毁窗口,彻底避免资源残留
  • CAP_DSHOW后端:Windows平台专属的摄像头后端,从根源减少异步回调的兼容性问题
  • 增加异常安全判断:防止摄像头读取失败、未检测到手势缺陷时出现崩溃
  • 最后加cv2.waitKey(1):解决Windows上destroyAllWindows()有时不生效的问题,确保窗口彻底关闭

这样修改后,那个异步回调的警告应该就会消失,同时你的程序鲁棒性也会提升不少。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 06:29:50