esp32cam+openCV图像分析传统家电LED面板数据反馈bliner APP-Arduino中文社区 - Powered by Discuz! Archiver

yuezhiying 发表于 2022-4-27 17:29

esp32cam+openCV图像分析传统家电LED面板数据反馈bliner APP

本帖最后由 yuezhiying 于 2022-4-27 17:56 编辑

      blinker改造一些传统家电时,比如热水器、空调等代有LED数字面板的设备时,用esp32或者8266进行远程红外遥控非常容,但无法得知遥控结果,不能得到返回数据。
   此方案通过用blinker APP 控制ESP32CAM对LED面板拍照后,将图片通过TCP发送至python架设的openCV图像分析程序的服务器,对图像进行分析,得到面板数据上的数据后,返回给ESP32CAM,ESP32CAM得到数据后在反馈给blinker APP,从而实现传统家电的LED面板图像信息数字化的转换。

       python openCV程序 就是开启了一个TCP server端等待图像接收,接受到图像后,通过openCV的模板匹配功能进行数字分析,因为这个应用场景时固定的,内容就上0-9的数字,所以不需要复杂的图形处理,只需要先把0-9的数字都拍照一遍制作成模板,在收到图像后对固定位置数字的图形区域进行裁剪,然后就行轮询匹配找到最相似的图形的索引号便得到数字结果。


python程序为3.1版本,需要安装openCV库。该代码模板匹配并通用,需要自行先将被识别的数字0-9先采集一遍保存至程序目录下的/num目录中作为模板,被识别的数字位置需要根据实际情况裁剪位置坐标。

import cv2
import numpy as np
from imutils import contours
import socket
import time

MaxBytes=1024*3024

def load_digits():
# 加载数字模板
    dig= []
    for q in range(0,10):
      img = cv2.imread("./num/num"+str(q)+".jpg") # 读取图片
      img = img
      img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度处理
         #自动阈值二值化 把图片处理成黑底白字
      img_temp = cv2.threshold(img_gray, 0, 255, cv2.THRESH_OTSU)

      kernel = np.ones((10, 10), np.uint8)
      img_temp = cv2.dilate(img_temp, kernel, iterations = 1)

      # cv2.imshow('num'+str(q), img_temp)
      dig.append(img_temp)#数字模板存入dig

    return dig

def cont_digits(img):
#模板匹配数字
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    img_temp = cv2.threshold(img_gray, 0, 255, cv2.THRESH_OTSU)

    kernel = np.ones((10, 10), np.uint8)
    img_temp = cv2.dilate(img_temp, kernel, iterations = 1)

    img_t = []
    img_t.append(img_temp)#裁剪第一个数字
    img_t.append(img_temp)#裁剪第二个数字

    cv2.imshow("img_t0",img_t)
    cv2.imshow("img_t1",img_t)

    num_out = []
    for img_T in img_t:   #对每个数字循环匹配十个数字模板
      source = []
      for dig_T in dig:
            res = cv2.matchTemplate(img_T, dig_T, cv2.TM_CCOEFF_NORMED)

            max_val = cv2.minMaxLoc(res)
            #print(max_val)
            source.append(max_val)   #每个模板匹配值存入source
      num_out.append(str(source.index(max(source)))) #取source最大值的索引号为匹配到的数字
      
    return num_out
    #print(num_out)

def bytes2cv(im):
    '''二进制图片转cv2
    :param im: 二进制图片数据,bytes
    :return: cv2图像,numpy.ndarray
    '''
    return cv2.imdecode(np.array(bytearray(im), dtype='uint8'), cv2.IMREAD_UNCHANGED)# 从二进制图片数据中读取

def cv2bytes(im):
    '''cv2转二进制图片
    :param im: cv2图像,numpy.ndarray
    :return: 二进制图片数据,bytes
    '''
    return np.array(cv2.imencode('.png', im)).tobytes()

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.settimeout(None)
host = '192.168.2.162'
#host = socket.gethostname()
port = 8889
server.bind((host, port))      # 绑定端口
j = 0
server.listen(1)                      # 监听

dig = load_digits()

while True:
    try:
      client,addr = server.accept()          # 等待客户端连接
      imgdata = []
      print(addr," 连接上了")
      while True:
            data = client.recv(MaxBytes)
            if not data:
                print('接收结束')
                break
            localTime = time.asctime( time.localtime(time.time()))
            print(localTime,' 接收到数据字节数:',len(data))
            if len(data) == 1 and data == b' ':
                print('接收结束')
                break
            imgdata.append(data)
      a = bytes()

      for i in imgdata:
            a = a + i

      img = bytes2cv(a)#接收到的二进制图像数据转换成openCV图像
      num = cont_digits(img)#进行图像分析
      
      print(num)#打印分析结果
      out_num = num+num

      client.send(out_num.encode('utf-8'))#向客户端返回分析结果
               

      cv2.imshow("fcrame",img)
      key = cv2.waitKey(1) & 0xFF
      # 按'q'健退出循环
      if key == ord('q') or cv2.waitKey(1)&0xff == 27:
            break

      
    except BaseException as e:
      print("出现异常:")
      print(repr(e))



yuezhiying 发表于 2022-4-27 17:48

实测效果



该方案虽然有点绕弯子,但是适用方向比较广,只要可以拍照的面板都可做识别,无需修改硬件获取反馈数据。
图像识别服务器可以搭建在公网,给不同得设备公用,或者搭建在家里的nas、树莓派、香橙派等都可。

yuezhiying 发表于 2022-4-27 17:36

Arduino 代码中使用了esp32cam.h库在附件中下载,blinker程序只是测试返回数据,没有写其他功能。

#define BLINKER_WIFI

#include <Blinker.h>
#include <esp32cam.h>


static auto hiRes = esp32cam::Resolution::find(800, 600);

char auth[] = "*****";
char ssid[] = "******";
char pswd[] = "******";

const uint16_t port = 8889;//python openCV服务器端口
const char * host = "192.168.2.162"; //python openCV服务器地址

// 新建组件对象
BlinkerButton Button1("btn-up");
BlinkerButton Button2("btn-down");
BlinkerNumber Number1("num");

int counter = 0;

// 按下按键即会执行该函数
void button1_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);
    serveJpg();
}


void button2_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);
    serveJpg();
}

// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);
}


void serveJpg()
{
auto frame = esp32cam::capture();
if (frame == nullptr) {
    Serial.println("CAPTURE FAIL");
    return;
}
Serial.printf("CAPTURE OK %dx%d %db\n", frame->getWidth(), frame->getHeight(),
                static_cast<int>(frame->size()));
               

WiFiClient client;
client.connect(host, port);
frame->writeTo(client);
delay(100);
client.write(" ");
while (client.connected() || client.available()){
    if (client.available()){
      String line = client.readString();
      Serial.println(line);
      Number1.print(line.toInt());
      client.stop();
    }
}
}

void setup()
{
    // 初始化串口
    Serial.begin(115200);
    BLINKER_DEBUG.stream(Serial);
    //BLINKER_DEBUG.debugAll();

    // 初始化blinker
    Blinker.begin(auth, ssid, pswd);
    Blinker.attachData(dataRead);

    Button1.attach(button1_callback);
    Button2.attach(button2_callback);
{
    using namespace esp32cam;
    Config cfg;
    cfg.setPins(pins::AiThinker);
    cfg.setResolution(hiRes);
    cfg.setBufferCount(2);
    cfg.setJpeg(80);

    bool ok = Camera.begin(cfg);
    Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");
}
   
}

void loop() {
    Blinker.run();
}

yuezhiying 发表于 2022-4-27 17:51

该项目未使用系统自带esp32cam库,使用附件中的库。

shouji6406 发表于 2022-4-27 18:54

希望不是搬的,才刚刷到视频,支持ZR

点灯官方 发表于 2022-4-27 21:33

刚在抖音看了,很棒。
其实我们也在服务器上装了OCR和人脸识别,但对服务器压力比较大,还在研究如何提供服务。
我觉得自己部署也是个很好的方式,我们会考虑下提供一个自己部署识别的方案。

yuezhiying 发表于 2022-4-28 11:08

点灯官方 发表于 2022-4-27 21:33
刚在抖音看了,很棒。
其实我们也在服务器上装了OCR和人脸识别,但对服务器压力比较大,还在研究如何提供服 ...

那可太好了,希望点灯科技越做越好!

cciew 发表于 2022-4-29 18:21

15行的 img[ 200:540,120:670] 这个img的参数怎么解读?模板有什么要求吗,能有白边吗?我运行起来的识别正确率很低.

tiejw 发表于 2022-5-23 22:25

太棒了,我也真想用这种方法来改造一下我的热水器。
页: [1]
查看完整版本: esp32cam+openCV图像分析传统家电LED面板数据反馈bliner APP