萤石云摄像头api+百度飞桨OCR 实现非智能电表读表

 功能实现远程读取非智能电表的用电量,并记录到Excel,每月15号定时统计计算,发送电量到微信,

上代码,功能有打开浏览器并截图,ocr识别电表读数,记录到Excel,和上个月做对比,计算出一个月的用电量。

import datetime
from paddleocr import PaddleOCR, draw_ocr
from PIL import Image, ImageGrab
import openpyxl
from openpyxl import Workbook
import pygetwindow as gw
from pywinauto import Application
import time
import requests
import json
import re
from requests.exceptions import HTTPError, RequestException
def send_request(method, url, headers=None, data=None, json_data=None):
    """通用请求函数"""
    try:
        response = requests.request(method, url, headers=headers, data=data, json=json_data, allow_redirects=False)
        response.raise_for_status()
        return response
    except HTTPError as http_err:
        print(f'HTTP error occurred: {http_err}')
    except RequestException as req_err:
        print(f'Request error occurred: {req_err}')
    return None
def send_wx_message(content, contenttype):
    """发送微信消息"""
    url = "http://127.0.0.1:5555/api/sendATMsg"
    payload = {
        "para": {
            "id": "{{date_time}}",
            "roomid": "null",
            "wxid": "12298079682@chatroom",
            #"wxid": "38950634091@chatroom",
            "content": content,
            "type": contenttype,
            "nickname": "三块钱",
            "ext": "null"
        }
    }
    headers = {'Content-Type': 'application/json'}
    response = requests.post(url, headers=headers, data=json.dumps(payload))
    if response:
        print(response.text)

def capture_window_by_keyword(keyword, region=None, output_file='selected_window_screenshot.png'):
    windows = gw.getAllWindows()
    matched_windows = [window for window in windows if keyword.lower() in window.title.lower()]
    if not matched_windows:
        print(f'No windows found with the keyword: {keyword}')
        return
    selected_window = matched_windows[0]
    app = Application().connect(handle=selected_window._hWnd)
    app.top_window().set_focus()
    time.sleep(1)
    x1, y1 = selected_window.left, selected_window.top
    x2, y2 = selected_window.right, selected_window.bottom
    if region:
        region_x1, region_y1, region_x2, region_y2 = region
        x1 += region_x1
        y1 += region_y1
        x2 = x1 + (region_x2 - region_x1)
        y2 = y1 + (region_y2 - region_y1)
    bbox = (x1, y1, x2, y2)
    screenshot = ImageGrab.grab(bbox)
    screenshot.save(output_file)
    print(f'Screenshot saved to {output_file}')

def extract_numbers(string):
    numbers = re.findall(r'\d+', string)
    return ''.join(numbers)

def perform_ocr(img_path):
    ocr = PaddleOCR(use_angle_cls=True, lang="ch")
    result = ocr.ocr(img_path, cls=True)
    for idx in range(len(result)):
        res = result[idx]
        for line in res:
            print(line)
    result2 = result[0]
    image = Image.open(img_path).convert('RGB')
    boxes = [line[0] for line in result2]
    txts = [line[1][0] for line in result2]
    scores = [line[1][1] for line in result2]
    im_show = draw_ocr(image, boxes, txts, scores, font_path='./fonts/simfang.ttf')
    im_show = Image.fromarray(im_show)
    #im_show.save('3.jpg')
    
    count = len(result[0])
    print(count)
    
    start_index = None
    end_index = None
    target_text = None
    
    for i, line in enumerate(result[0]):
        text = line[1][0]
        if text == '十':
            start_index = i
        elif text == '★':
            end_index = i
        elif start_index is not None and end_index is None:
            target_text = text
            box = line[0]
            score = line[1][1]
            break
    
    if target_text:
        print(f"识别文本: {target_text}, 置信度: {score}")
        print(f"识别文本: {extract_numbers(target_text)}, 置信度: {score}")
        im_show = draw_ocr(image, [box], [target_text], [score], font_path='./fonts/simfang.ttf')
        im_show = Image.fromarray(im_show)
        im_show.save('extracted_target_text.png')
        #im_show.show()
        return extract_numbers(target_text)
    else:
        print("未找到目标文本")
        return None

def read_meter(file_path):
    try:
        wb = openpyxl.load_workbook(file_path)
        sheet = wb.active
        if sheet.max_row > 1:
            last_row = sheet[sheet.max_row]
            last_date = last_row[0].value
            last_reading = last_row[1].value
            if last_date and last_reading is not None:
                last_reading = int(last_reading)
                return last_date, last_reading
            else:
                return None, 0
        else:
            return None, 0
    except FileNotFoundError:
        return None, 0

def write_meter(file_path, date, reading):
    try:
        wb = openpyxl.load_workbook(file_path)
    except FileNotFoundError:
        wb = Workbook()
        sheet = wb.active
        sheet.append(["日期", "读数"])
    sheet = wb.active
    sheet.append([date, reading])
    wb.save(file_path)

def calculate_usage(file_path, current_date, current_reading):
    last_date, last_reading = read_meter(file_path)
    usage = current_reading - last_reading
    write_meter(file_path, current_date, current_reading)
    return last_date, last_reading, current_date, current_reading, usage

# 主程序
img_path = 'D:\电表\selected_window_screenshot.png'
file_path = 'D:\电表\meter_readings.xlsx'

# 从图像中提取电表读数
text = perform_ocr(img_path)
if text is not None:
    try:
        current_reading = int(text)
        current_date = datetime.datetime.now()
        last_date, last_reading, current_date, current_reading, usage = calculate_usage(file_path, current_date, current_reading)
        print(f"上次读数是在 {last_date.strftime('%Y-%m-%d')},读数为 {last_reading} 度。")
        print(f"当前读数是在 {current_date.strftime('%Y-%m-%d')},读数为 {current_reading} 度。")
        print(f"这段时间的用量为 {usage } 度。")
        send_wx_message(f"上次读数是在 {last_date.strftime('%Y-%m-%d')},读数为 {last_reading} 度。\n当前读数是在 {current_date.strftime('%Y-%m-%d')},读数为 {current_reading} 度。\n这段时间的用量为 {usage } 度。电费费用为:{usage*1}元" ,555)
        send_wx_message(f"D:/电表/3.jpg" ,500)
    except ValueError:
        print("无法将识别结果转换为整数。")

萤石云摄像头,申请appKey和appSecret 获取摄像头直播地址,如何生成html文件,预览视频

import requests
import json
def getysyTaken():
    url = "https://open.ys7.com/api/lapp/token/get?appKey=6980b***************d72b&appSecret=7ab3*********0b72"

    payload = {}
    files={}
    headers = {}

    response = requests.request("POST", url, headers=headers, data=payload, files=files, allow_redirects=False)

    print(response.text)
    response = response.json()
    return (response['data']['accessToken'])

access_token = getysyTaken()
html_content = f'''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>摄像头</title>
    <script src="ezuikit.js"></script>
    <style>
        html,body {{
            padding: 0;
            margin: 0;
            text-align: center;
            background: #00000080;
            overflow: hidden;
        }}
    </style>
</head>
<body>
    <div id="playWind"></div>
    <script>
        var domain = "https://open.ys7.com";
        var EZOPENDemo;
        window.EZOPENDemo = EZOPENDemo;
        var width = document.documentElement.clientWidth;
        var height = document.documentElement.clientHeight;
        const ezopenInit = () => {{
            EZOPENDemo = new EZUIKit.EZUIKitPlayer({{
                id: 'playWind',
                width: '800',
                height: '500',
                template: "simple",
                url: "ezopen://open.ys7.com/798797360/1.live",
                accessToken: "{access_token}"
            }});
        }}
        ezopenInit();
    </script>
</body>
</html>
'''

# 将HTML内容写入文件
with open('index.html', 'w', encoding='utf-8') as file:
    file.write(html_content)

print("index.html 文件已生成")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三块钱0794

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值