2114浏览
查看: 2114|回复: 1

[项目] 【智控万物】懒人系列之视控灯

[复制链接]
【智控万物】懒人系列之视控灯
【智控万物】懒人系列之视控灯图3

(演示:视频识别控制Microbit)


【项目背景】

"视控灯"这个名字来自“声控灯”,在公共场所,有人需要临时开灯。如楼道、卫生间等等。声控灯实现起来很简单,应用比较普遍。声控是它的优势但也存在一个很大的问题。因为只有声音超过一定响度时,灯才亮。这也就出现了有人在楼门口大声咳嗽,使劲跺脚。同时也发生在楼道里,不方便自己的同时,也产生了噪音,尤其是在深夜,你的大呵一声,惊扰四邻。

【设计方案】

1、现在使用的是电脑作为识别工具,后期条件成熟准备使用树莓派,因Python在树莓派也能实现相应功能。

2、使用Python来处理摄像头图像,代码简单,本地运行速度快。识别响应阈值可自定义。

3、CodeLab Scratch3+CodeLab Adapter+Python完美搭配。以前我要实现类似功能,要通过一个中间者MQTT,比如本地的像Siot

【准备工作】


【制作过程】

1、只使用Python进行测试

《演示视频》


[mw_shl_code=python,false]#识别画面异动
import imutils,cv2,time

camera = cv2.VideoCapture(0)
framefirst=None
avg=None
num=0
j=0
while True:
    (grabbed, frame) = camera.read()
    # 如果不能抓取到一帧,说明我们到了视频的结尾
    if not grabbed:
        break

    # 调整该帧的大小,并且对其进行高斯模糊
    frame = imutils.resize(frame, width=500)
    imageold=frame.copy()
    #转换为灰阶图像
    gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

    #高斯模糊 这里(21, 21)表示高斯矩阵的长与宽都是5,
    #标准差取0时OpenCV会根据高斯矩阵的尺寸自己计算。概括地讲,高斯矩阵的尺寸越大,标准差越大,处理过的图像模糊程度越大。
    gray = cv2.GaussianBlur(gray, (21, 21), 0)
    if framefirst is None :
       framefirst=gray
       continue
    if avg is None:
       avg = gray.copy().astype("float")
       continue
    #图像叠加or图像混合加权实现
    #cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst
    #dst = src1 * alpha + src2 * beta + gamma;
    cv2.accumulateWeighted(gray, avg, 0.5)
    gray = cv2.absdiff(gray, cv2.convertScaleAbs(avg))

    # 二值化处理,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图 ,
    #像素高于阈值时,给像素赋予新值,否则,赋予另外一种颜色。函数是cv2.threshold()
    ret, binary = cv2.threshold(gray,5,255,cv2.THRESH_BINARY)
    #学习不同的形态学操作,例如腐蚀,膨胀,开运算,闭运算等
    #我们要学习的函数有:cv2.erode(),cv2.dilate(),cv2.morphologyEx()等
    #与卷积核对应的原图像的像素值中只要有一个是1,中心元 素的像素值就是1。所以这个操作会增加图像中的白色区域(前景)。
    #一般在去噪声时先用腐蚀再用膨胀。因为腐蚀在去掉白噪声的同时,也会使前景对象变小。
    #所以我们再对他进行膨胀。这时噪声已经被去除了,不会再回来了,但是前景还在并会增加。膨胀也可以用来连接两个分开的物体。
    thresh = cv2.dilate(binary, None, iterations=2)
    #binary:寻找轮廓的图像
    #轮廓的检索模式:cv2.RETR_EXTERNAL表示只检测外轮廓
                    #cv2.RETR_TREE建立一个等级树结构的轮廓。
                    #cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    #第一个参数是指明在哪幅图像上绘制轮廓;
    #第二个参数是轮廓本身,在Python中是一个list。
    #第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1则绘制其中的所有轮廓。
    #thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。
    #
    cv2.drawContours(frame,contours,-1,(0,0,255),3)  

    for c in contours:
        # if the contour is too small, ignore it
        if cv2.contourArea(c) < 5000:
            continue

        # 计算轮廓线的外框, 在当前帧上画出外框,
        # 并且更新文本
        (x, y, w, h) = cv2.boundingRect(c)
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
   
        num+=1
        if num>20 :
           print('有异动')
           num=0
    cv2.imshow("contours", frame)
    #cv2.imshow("Gray", gray)
   
    #cv2.imshow("binary", binary)
    key = cv2.waitKey(1) & 0xFF

    # 如果q键被按下,跳出循环
    if key == ord("q"):
        break

# 清理摄像机资源并关闭打开的窗口
camera.release()
cv2.destroyAllWindows()[/mw_shl_code]


2、CodeLab Scratch3+CodeLab Adapter+Python,暂未控灯
《演示视频》


[mw_shl_code=python,false]import time
import imutils,cv2
from loguru import logger
from codelab_adapter_client import AdapterNode


class EIMNode(AdapterNode):
    def __init__(self):
        super().__init__()
        self.NODE_ID = "eim"

    def send_message_to_scratch(self, content):
        message = self.message_template()
        message["payload"]["content"] = content
        self.publish(message)

    def extension_message_handle(self, topic, payload):
        self.logger.info(f'the message payload from scratch: {payload}')
        content = payload["content"]
        if type(content) == str:
            content_send_to_scratch = content[::-1]  # 反转字符串
            self.send_message_to_scratch(content_send_to_scratch)

    def run(self):
        camera = cv2.VideoCapture(0)
        framefirst=None
        avg=None
        num=0
        j=0
        while self._running:
                (grabbed, frame) = camera.read()
                # 如果不能抓取到一帧,说明我们到了视频的结尾
                if not grabbed:
                    break

                # 调整该帧的大小,并且对其进行高斯模糊
                frame = imutils.resize(frame, width=500)
                imageold=frame.copy()
                #转换为灰阶图像
                gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

                #高斯模糊 这里(21, 21)表示高斯矩阵的长与宽都是5,
                #标准差取0时OpenCV会根据高斯矩阵的尺寸自己计算。概括地讲,高斯矩阵的尺寸越大,标准差越大,处理过的图像模糊程度越大。
                gray = cv2.GaussianBlur(gray, (21, 21), 0)
                if framefirst is None :
                   framefirst=gray
                   continue
                if avg is None:
                   avg = gray.copy().astype("float")
                   continue
                #图像叠加or图像混合加权实现
                #cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst
                #dst = src1 * alpha + src2 * beta + gamma;
                cv2.accumulateWeighted(gray, avg, 0.5)
                gray = cv2.absdiff(gray, cv2.convertScaleAbs(avg))

                # 二值化处理,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图 ,
                #像素高于阈值时,给像素赋予新值,否则,赋予另外一种颜色。函数是cv2.threshold()
                ret, binary = cv2.threshold(gray,5,255,cv2.THRESH_BINARY)
                #学习不同的形态学操作,例如腐蚀,膨胀,开运算,闭运算等
                #我们要学习的函数有:cv2.erode(),cv2.dilate(),cv2.morphologyEx()等
                #与卷积核对应的原图像的像素值中只要有一个是1,中心元 素的像素值就是1。所以这个操作会增加图像中的白色区域(前景)。
                #一般在去噪声时先用腐蚀再用膨胀。因为腐蚀在去掉白噪声的同时,也会使前景对象变小。
                #所以我们再对他进行膨胀。这时噪声已经被去除了,不会再回来了,但是前景还在并会增加。膨胀也可以用来连接两个分开的物体。
                thresh = cv2.dilate(binary, None, iterations=2)
                #binary:寻找轮廓的图像
                #轮廓的检索模式:cv2.RETR_EXTERNAL表示只检测外轮廓
                #cv2.RETR_TREE建立一个等级树结构的轮廓。
                #cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
                contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
                #第一个参数是指明在哪幅图像上绘制轮廓;
                #第二个参数是轮廓本身,在Python中是一个list。
                #第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1则绘制其中的所有轮廓。
                #thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。
                #
                cv2.drawContours(frame,contours,-1,(0,0,255),3)  

                for c in contours:
                    # if the contour is too small, ignore it
                    if cv2.contourArea(c) < 5000:
                        continue
            
                    # 计算轮廓线的外框, 在当前帧上画出外框,
                    # 并且更新文本
                    (x, y, w, h) = cv2.boundingRect(c)
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
   
                    num+=1
                    if num>20 :
                       self.send_message_to_scratch('有异动')
                       print('有异动')
                       num=0
                cv2.imshow("contours", frame)
                #cv2.imshow("Gray", gray)
   
                #cv2.imshow("binary", binary)
                key = cv2.waitKey(1) & 0xFF

                # 如果q键被按下,跳出循环
                if key == ord("q"):
                    break
        # 清理摄像机资源并关闭打开的窗口
        camera.release()
        cv2.destroyAllWindows()


if __name__ == "__main__":
    try:
        node = EIMNode()
        node.receive_loop_as_thread()
        node.run()
    except KeyboardInterrupt:
        node.terminate()  # Clean up before exiting.[/mw_shl_code]

3、CodeLab Scratch3加入Usb Microbit控制
【智控万物】懒人系列之视控灯图1


演示视频(不接电磁继电器和灯),直接用Microbit点阵灯演示



演示视频(接电磁继电器和灯)



种瓜  见习技师

发表于 2020-5-8 09:20:34

哈哈 挥手时光晕效果 有钢铁侠的味道
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail