Python3实现灯光检测

实际情况

目前无论基于电信号还是光信号的通信,都无法避免的有一定概率会发生“丢包‘’,这是因为光或者电信号传输都依赖“媒介”,而"媒介"的实际状态我们无法把控。比如CAN总线通信,是在一对导线上传递的差分电压信号。2.4G的无线,是在空间上传递的电磁波信号。而"媒介"的状态,比如CAN通信导线上的特征阻抗或许我们认为还能控制,但是导线周围的电磁环境呢?2.4G无线传输就更不必说了,空间上的一堵墙,一块铁板,就能明显的影响无线传输。
摆在我们面前的,就是我们如何证明我们的通信,是稳定的呢?
你的想法或许是这样:我们需要将每一次通信的“发起端”发起的时间和"结束端"接收的时间都记录下来,一一对应即可。这种想法没有问题,我们可以将发起端设备和结束端设备将记录时间的Log都统一输出到一个地方做记录统计,但是这种方法成本比较高。所以我们可以针对具体的产品,去做这个测试。
我手上的设备,通信的发起端设备可以通过通信的协议控制结束端设备上灯的亮灭,于是我们写一个测试程序,让发起端设备按一定次数控制终端亮灭(举个例子一万次),我们则根据接收端实际亮灭的的次数来判断通信的丢包率。而这种测试方式,需要一个能实现灯光检测的图像识别软件(判断灯亮灭的状态)。用Python3来利用笔记本上的摄像头来实现起来代码不超过150行。

Python3代码

找个带有摄像头的笔记本,安装PyCharm,你可以理解它为Python的IDE。为了实现光电的图像识别,我们需要导入CV2以及numpy两个Package。打开当前的工程的设置,点开Project Interpreter,点击右侧的加号,增加这两个库。
在这里插入图片描述
代码将摄像头捕捉的图像输出到一个窗口上,我们重写窗口有鼠标点下的事件函数,记录当前鼠标的坐标信息。
我们在捕捉到图像的时候,如果有记录的坐标信息,则在坐标周围画一个黑色圆圈,表示我们监控这个圆圈内的灯的亮灭。然后我们这个圆圈内部的RGB值的信息来判断是否亮灯,并输出记录为.CSV文件,具体代码如下。(代码写的C风格比较重,如果熟悉Python的人应该能写的更短更好看)

import cv2
import time
import numpy
from numpy import *
import datetime
import numpy as np

CirclLightNumber=12

MousClickNumber=0
MousClickTable=numpy.zeros(shape=(CirclLightNumber,2)) #第一个参数为点的

LightState=[0,0,0,0,0,0,0,0,0,0,0,0]

LightUpNumber=[0,0,0,0,0,0,0,0,0,0,0,0]
LightDownNumber=[0,0,0,0,0,0,0,0,0,0,0,0]
AverageLight=[0,0,0,0,0,0,0,0,0,0,0,0]

ALightUpNumber=0
ALightDownNumber=0
ALightState=0
ALightArrSta=[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]
ALightUpN=0
ALightDownN=0

WhLoopIndex=0

def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        global MousClickNumber
        MousClickTable[MousClickNumber] =[y, x]
        MousClickNumber=MousClickNumber+1
        if MousClickNumber>(CirclLightNumber-1):#循环头
            MousClickNumber=0

cap = cv2.VideoCapture(0)

cv2.namedWindow("image")
cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)

time_creat = datetime.datetime.now().strftime('%H%M%S.csv')

fout = open(time_creat,encoding='utf8',mode='w')

content = "%s,%s,%s\n" % ("Index","State", "Time,")
fout.write(content)


while(1):
    # get a frame and show
    ret, frame = cap.read()
    WhLoopIndex=WhLoopIndex+1
    if WhLoopIndex >2:
        WhLoopIndex=0

    for index  in range(MousClickNumber):
        kin=int(MousClickTable[index][0])
        lin=int(MousClickTable[index][1])
        '''
        xy = "%d,%d,%d" % (frame[kin, lin, 0], frame[kin,lin , 1], frame[kin, lin, 2])
        cv2.putText(frame, xy, (lin, kin), cv2.FONT_HERSHEY_PLAIN,
                    1.0, (0, 0, 0), thickness=1)
        '''
        #获取采样点周围5个点的亮度值
        xy = "%d|" % (index)
        AverageLight[0]=(int(frame[kin, lin, 0])+int(frame[kin, lin, 1])+int(frame[kin, lin, 2]))/3
        AverageLight[1]= (int(frame[(kin+1), lin, 0]) + int(frame[(kin+1), lin, 1]) + int(frame[(kin+1), lin, 2])) / 3
        AverageLight[2]= (int(frame[(kin), (lin+1), 0]) + int(frame[(kin), (lin+1), 1]) + int(frame[(kin), (lin+1), 2])) / 3
        AverageLight[3]= (int(frame[(kin-1), lin, 0]) + int(frame[(kin-1), lin, 1]) + int(frame[(kin-1), lin, 2])) / 3
        AverageLight[4] = (int(frame[(kin), (lin-1), 0]) +int(frame[(kin), (lin-1), 1]) + int(frame[(kin), (lin-1), 2])) / 3

        ALightUpNumber=0;
        ALightDownNumber=0;
        ALightUpN=0;
        ALightDownN=0;

        #5个点中 >220为灯亮 <=则为灯灭
        for indexIn in range(5):
            if AverageLight[indexIn] >  220:
                ALightUpNumber=ALightUpNumber+1
            else:
                ALightDownNumber=ALightDownNumber+1
        #灯亮的次数为3~5,则记录此次循环的状态为灯亮
        if ALightUpNumber>2:
            ALightArrSta[index][WhLoopIndex]=250
        else:
            ALightArrSta[index][WhLoopIndex]=150

        # 针对这个LightBow,3个历史记录的点中 >220为灯亮 <=则为灯灭
        for indexIn in range(3):
            if ALightArrSta[index][indexIn] > 220:
                ALightUpN =ALightUpN+1
            else:
                ALightDownN = ALightDownN + 1

        # 在历史中,有两次即为灯亮
        if ALightUpN>1:
            ALightState=250
        else:
            ALightState=150

        if ALightState>220 and LightState[index]==0:#检测到灯亮
            #xyz = "%d,%d,%d" % (frame[kin, lin, 0], frame[kin, lin, 1], frame[kin, lin, 2])
            #print(xyz)
            LightState[index]=1
            time_now = datetime.datetime.now().strftime('%H:%M:%S.%f')
            print("%d,%d,%s" % (index,1,time_now))
            content = "%d,%d,%s\n" % (index, 1, time_now)
            fout.write(content)
            LightUpNumber[index]=LightUpNumber[index]+1
        if ALightState <220 and LightState[index] == 1:#检测到灯灭
            #xyz = "%d,%d,%d" % (frame[kin, lin, 0], frame[kin, lin, 1], frame[kin, lin, 2])
            #print(xyz)
            LightState[index] = 0
            time_now = datetime.datetime.now().strftime('%H:%M:%S.%f')
            #print("%d,%d,%s" % (index,0,time_now))
            content="%d,%d,%s\n" % (index, 0, time_now)
            fout.write(content)
            LightDownNumber[index] = LightDownNumber[index] + 1
            #print(LightDownNumber[index] )
        cv2.circle(frame, (lin, kin), 10, (50, 50, 50), thickness=2)
        cv2.putText(frame, xy, (lin,(kin-10)), cv2.FONT_HERSHEY_PLAIN,
                          1.0, (0, 0, 0), thickness=2)


    cv2.imshow("image", frame)
    #h, w, _ = frame.shape  # 返回height,width,以及通道数,不用所以省略掉
    #print('行数%d,列数%d' % (h, w))

    time.sleep(0.1)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
fout.close()

fout = open("Result"+time_creat,encoding='utf8',mode='w')
#fout.seek(15,0)
fout.write("Index,LightUpUmber,LightDownUmber\n")
for index  in range(MousClickNumber):
    ReContent = "%d,%d,%d\n" % ((index),LightUpNumber[index], LightDownNumber[index])
    fout.write(ReContent)
fout.close()
cv2.destroyAllWindows()

在这里插入图片描述

原创文章 21 获赞 29 访问量 2万+

猜你喜欢

转载自blog.csdn.net/geek_liyang/article/details/90769856