python-opencv 矩形框显示不出来

用Python opencv调用工业摄像头进行帧差法进行动态跟踪,代码能成功运行但是矩形框画不出来,

coding=utf-8

import cv2
import numpy as np
import mvsdk
import platform

class Camera(object):
def init(self, DevInfo):
super(Camera, self).init()
self.DevInfo = DevInfo
self.hCamera = 0
self.cap = None
self.pFrameBuffer = 0

def open(self):
    if self.hCamera > 0:
        return True

    # 打开相机
    hCamera = 0
    try:
        hCamera = mvsdk.CameraInit(self.DevInfo, -1, -1)
    except mvsdk.CameraException as e:
        print("CameraInit Failed({}): {}".format(e.error_code, e.message))
        return False

    # 获取相机特性描述
    cap = mvsdk.CameraGetCapability(hCamera)

    # 判断是黑白相机还是彩色相机
    monoCamera = (cap.sIspCapacity.bMonoSensor != 0)

    # 黑白相机让ISP直接输出MONO数据,而不是扩展成R=G=B的24位灰度
    if monoCamera:
        mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8)
    else:
        mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8)

    # 计算RGB buffer所需的大小,这里直接按照相机的最大分辨率来分配
    FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3)

    # 分配RGB buffer,用来存放ISP输出的图像
    # 备注:从相机传输到PC端的是RAW数据,在PC端通过软件ISP转为RGB数据(如果是黑白相机就不需要转换格式,但是ISP还有其它处理,所以也需要分配这个buffer)
    pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16)

    # 相机模式切换成连续采集
    mvsdk.CameraSetTriggerMode(hCamera, 0)

    # 手动曝光,曝光时间30ms
    mvsdk.CameraSetAeState(hCamera, 0)
    mvsdk.CameraSetExposureTime(hCamera, 30 * 1000)

    # 让SDK内部取图线程开始工作
    mvsdk.CameraPlay(hCamera)

    self.hCamera = hCamera
    self.pFrameBuffer = pFrameBuffer
    self.cap = cap
    return True

def close(self):
    if self.hCamera > 0:
        mvsdk.CameraUnInit(self.hCamera)
        self.hCamera = 0

    mvsdk.CameraAlignFree(self.pFrameBuffer)
    self.pFrameBuffer = 0

def grab(self):
    # 从相机取一帧图片
    hCamera = self.hCamera
    pFrameBuffer = self.pFrameBuffer
    try:
        pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 200)
        mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead)
        mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)

        # windows下取到的图像数据是上下颠倒的,以BMP格式存放。转换成opencv则需要上下翻转成正的
        # linux下直接输出正的,不需要上下翻转
        if platform.system() == "Windows":
            mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1)

        # 此时图片已经存储在pFrameBuffer中,对于彩色相机pFrameBuffer=RGB数据,黑白相机pFrameBuffer=8位灰度数据
        # 把pFrameBuffer转换成opencv的图像格式以进行后续算法处理
        frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer)
        frame = np.frombuffer(frame_data, dtype=np.uint8)
        frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth,
                               1 if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8 else 3))
        return frame
    except mvsdk.CameraException as e:
        if e.error_code != mvsdk.CAMERA_STATUS_TIME_OUT:
            print("CameraGetImageBuffer failed({}): {}".format(e.error_code, e.message))
        return None

def main_loop():
# 枚举相机
DevList = mvsdk.CameraEnumerateDevice()
nDev = len(DevList)
if nDev < 1:
print("No camera was found!")
return

for i, DevInfo in enumerate(DevList):
    print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType()))

cams = []
for i in range(2):
    cam = Camera(DevList[i])
    if cam.open():
        cams.append(cam)

while (cv2.waitKey(1) & 0xFF) != ord('q'):
    for cam in cams:
        frame = cam.grab()
        if frame is not None:
            frame = cv2.resize(frame, (640, 480), interpolation=cv2.INTER_LINEAR)
            frame = process_frame(frame)
            cv2.imshow("{} Press q to end".format(cam.DevInfo.GetFriendlyName()), frame)

def process_frame(frame):
es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 4)) # 返回指定形状和尺寸的结构元素,椭圆形,中心点
kernel = np.ones((5, 5), np.uint8) # 返回矩阵
background = None
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)

# 将第一帧设置为整个输入的背景

background = gray

# 对于每个从背景之后读取的帧都会计算其与背景之间的差异,并得到一个差分图(different map)。
# 还需要应用阈值来得到一幅黑白图像,并通过下面代码来膨胀(dilate)图像,从而对孔(hole)和缺陷(imperfection)进行归一化处理
diff = cv2.absdiff(background, gray)
diff = cv2.threshold(diff, 148, 255, cv2.THRESH_BINARY)[
    1]  # 二值化阈值处理黑白,灰度图,对图像进行分类的阈值,最大值,表示如果像素值大于(有时小于)阈值则要给出的值,决定给出不同类型的阈值
diff = cv2.dilate(diff, es, iterations=2)  # 形态学膨胀,目标图片,进行操作的内核,默认为3×3的矩阵,腐蚀次数,默认为1
# 显示矩形框
contours, hierarchy = cv2.findContours(diff.copy(), cv2.RETR_EXTERNAL,
                                       cv2.CHAIN_APPROX_SIMPLE)  # 该函数计算一幅图像中目标的轮廓,只返回最外边轮廓,
# contours:返回的轮廓     hierarchy:每条轮廓对应的属性
for c in contours:
    if cv2.contourArea(c) < 1500:  # 求得轮廓面积 对于矩形区域,只显示大于给定阈值的轮廓,所以一些微小的变化不会显示。对于光照不变和噪声低的摄像头可不设定轮廓最小尺寸的阈值
        continue
    (x, y, w, h) = cv2.boundingRect(c)  # 该函数计算矩形的边界框,x,y是矩阵左上点的坐标,w,h是矩阵的宽和高
    cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
return frame

def main():
try:
main_loop()
finally:
cv2.destroyAllWindows()

main()

img

这种只能debug进去看下了,看看是不是你最后找的轮廓没有找到没绘制,还是你找到的轮廓面积全部小于1500所以没进去下面的绘制函数

在怀疑有问题的地方插入

print("变量名: "+str(变量名))
input(“pause”)

辅助调试