利用单片机在封闭环境下计算水下物体数量

2024-03-02 13:20

本文主要是介绍利用单片机在封闭环境下计算水下物体数量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、架构图及流程图

二、ESP32-CAM代码

三、Web服务器

四、图像处理程序代码

五、前端代码

六、使用流程

总结



前言

随着当今社会的发展,水产品市场作为一个重要的食品供应领域,其规模庞大且竞争激烈。然而,在售卖水产品时,例如螃蟹,虾等,通常需要按照数量来计算和售卖,这个传统的方式不仅耗费了大量的人力和时间资源,还容易引发计算错误,导致盈利能力下降。

传统的水产品销售方式主要依赖于人工计算,这需要雇佣大量的工作人员来记录、计算和核对订单。这不仅增加了人力成本,还容易出现计算错误,导致产品的过多或过少售出,从而损害了盈利能力和客户满意度。此外,传统方式也会导致资源浪费。

所以传统的水产品销售方式在当今社会已经不再适用,因为它浪费了资源,容易出现错误,降低了盈利能力。本文便设计了一种基于单片机的设备,旨在在封闭环境下计算水下物体的数量,从而提高售卖过程的效率和精度。通过采用现代技术和数字化销售方式,水产品市场可以提高效率,减少成本,更好地满足客户和商户的需求,从而在竞争激烈的市场中保持竞争力。

一、架构图及流程图

架构图

流程图

二、ESP32-CAM代码

import machine
import time
import network
import ntptime
import urequests as requests
from machine import Timer, Pin# 声明引脚 13 作为LED的引脚
red_pin = Pin(13, Pin.OUT)
timer = Timer(1)  # 创建定时器对象
(ST_INIT, ST_READY, ST_BUSY) = (300, 0, 100)def toggle_led(red_pin):red_pin.value(not red_pin.value())
#指示灯
def led_blink_timed(timer, red_pin, state):#就绪if state == 'READY':timer.deinit()red_pin.value(ST_READY)#初始elif state == 'INIT':timer.init(period=ST_INIT, mode=Timer.PERIODIC, callback=lambda t: toggle_led(red_pin))#忙碌elif state == 'BUSY':timer.init(period=ST_BUSY, mode=Timer.PERIODIC, callback=lambda t: toggle_led(red_pin))else:print('not define yet')# 定时器触发
led_blink_timed(timer, red_pin, state='INIT')# 连接到 Wi-Fi 网络
def connectWiFi():wlan = network.WLAN(network.STA_IF)wlan.active(True)if not wlan.isconnected():print("连接到Wi-Fi网络...")wlan.connect('ESP32','123456789')while not wlan.isconnected():passprint('网络配置: ', wlan.ifconfig())led_blink_timed(timer, red_pin, state='INIT')
connectWiFi()# freq设置PWM频率,duty设置初始占空比为1023
led_pin = machine.PWM(machine.Pin(4), freq=1000, duty=1023)def led_control(current_brightness, led_pwm):if current_brightness == 1023:current_brightness = 100elif current_brightness == 100:current_brightness = 50elif current_brightness == 50:current_brightness = 1023else:current_brightness = 1023  # 如果当前亮度无效,将其设置为默认值1023led_pwm.duty(current_brightness)  # 更新LED亮度return current_brightness# 在主循环中初始化 LED 亮度
led_brightness = 1023import camera
# 拍照并上传图片
def image_upload():flask_url = 'http://172.20.10.2:5000/esp32_im'led_blink_timed(timer, red_pin, state='BUSY')# 初始化摄像头while not camera.init(0, format=camera.JPEG, fb_location=camera.PSRAM):time.sleep(1)frame = camera.capture()print("拍摄完成")camera.deinit()led_blink_timed(timer, red_pin, state='READY')r = requests.post(flask_url, headers={'content-type': 'image/jpeg'}, data=frame)return r.json(), 200, {'Content-Type': 'application/json'}# 初始化按钮引脚
button_pin = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)
if __name__ == '__main__':button_state = button_pin.value()  # 初始化按钮状态last_trigger_time = 0  # 上次触发操作的时间last_button_state = 1  # 初始状态为按键未按下last_click_time = 0double_click_timeout = 3  # 双击的最大时间间隔min_double_click_interval = 1  # 最小双击间隔,单位为秒debounce_delay = 50  # 消抖延迟,毫秒while True:current_time = time.ticks_ms()  # 获取当前时间,以便检查是否达到了消抖延迟。# 检查消抖延迟是否满足if current_time - last_trigger_time >= debounce_delay:new_button_state = button_pin.value()  # 读取按钮引脚的当前状态if new_button_state != button_state:# 按钮状态改变button_state = new_button_stateif button_state == 0:# 根据单击或双击执行不同的操作time_since_last_click = current_time - last_click_timeprint(time_since_last_click)if (time_since_last_click > min_double_click_interval * 1000and time_since_last_click < double_click_timeout * 1000):led_brightness = led_control(led_brightness, led_pin)print("亮度:",led_brightness)else:print("单击操作")print("发送照片")image_upload()print("发送成功")last_click_time = current_timelast_trigger_time = current_time

注释:照明LED是ESP32-CAM自带的灯,引脚为4,按钮接的引脚为12。状态灯red,接的引脚为13。

三、Web服务器

from flask import Flask, request, jsonify,render_template
from flask_cors import cross_origin
import time
import os
from countstone import countstones
app = Flask(__name__)
@app.route("/esp32_im", methods=["POST","GET"])
def process_image():print("保存图片1")imageData = request.get_data(parse_form_data=False)filename = time.strftime("%m%d%H%M%S", time.localtime()) + ".jpg"path = "./images/" + str(filename)file = open(path, "wb")file.write(imageData)countstones()print("图片已处理")return jsonify({'msg': '图片已保存'})@app.route("/send_image", methods=["GET"])
def send_image1():# 获取最新的照片发送到前端显示print("开始发送图片到前端")maxnum = []picturePath = './static/finsh/'for fi in os.listdir(picturePath):if fi.endswith(".jpg"):maxnum.append(int(fi[0:10]))maxPhoto = max(maxnum)# print(max(maxnum))path = "./static/finsh/"  + str(maxPhoto) + ".jpg"#frame = open(path, 'rb')print(path)return render_template('index.html', image_url=path)
if __name__ == "__main__":app.run(host='0.0.0.0',debug=True,)   

四、图像处理程序代码

import cv2
import os
import numpy as np
from matplotlib.pyplot import figure, imshow, axis,showdef countstones():maxnum = []picturePath = './images'for fi in os.listdir(picturePath):if fi.endswith(".jpg"):maxnum.append(int(fi[0:10]))maxPhoto = max(maxnum)path = "./images/"  + str(maxPhoto) + ".jpg"img = cv2.imread(path)# Apply Gamma=0.4 on the normalised image and then multiply by scaling constant (For 8 bit, c=2 5)gamma_point_four = np.array(255*(img/255)**0.4,dtype='uint8')# Similarly, Apply Gamma=0.8gamma_point_eight = np.array(255*(img/255)**0.9,dtype='uint8')# Display the images in subplotsimg3 = cv2.hconcat([gamma_point_four,gamma_point_eight])frame = cv2.normalize(gamma_point_eight, None, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)# scale to uint8frame = (255*frame).astype(np.uint8)image = frame[80:450, 130:520] # 找出ROIhsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)# 转换颜色空间 BGR 到 HSV# 定义HSV中蓝色的范围color_dist = {'red': {'Lower': np.array([0, 43,46]), 'Upper': np.array([13, 255, 255])},'blue': {'Lower': np.array([75, 28, 65]), 'Upper': np.array([120, 255, 220])},'green': {'Lower': np.array([35, 43, 35]), 'Upper': np.array([90, 255, 255])},'pink': {'Lower': np.array([156, 43, 46]), 'Upper': np.array([180, 255, 255])},'yellow': {'Lower': np.array([26, 43, 46]), 'Upper': np.array([34, 255, 255])},}filterStone = 'blue'lower_blue = color_dist[filterStone]['Lower'] upper_blue = color_dist[filterStone]['Upper'] # 设置HSV的阈值使得只取蓝色mask = cv2.inRange(hsv, lower_blue, upper_blue) # 过滤蓝色石头# 将掩膜和图像逐像素相加res = cv2.bitwise_and(image,image, mask= mask)res2rgba = cv2.cvtColor(res, cv2.COLOR_BGR2RGBA)# 透过开运算取得蓝色石头所在位置erode_hsv = cv2.erode(mask, None, iterations=1)dilated_hsv = cv2.dilate(erode_hsv, None, iterations=1)# 去除小的轮廓(噪点)min_contour_area = 2 # 轮廓的最小面积,根据需要调整lunkuo_img=image.copy()#获取轮廓_,binary=cv2.threshold(erode_hsv,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)filtered_contours = [contour for contour in contours if cv2.contourArea(contour) >= min_contour_area]num_filtered_contours = len(filtered_contours)print("过滤后的轮廓数量:", num_filtered_contours)# 画出轮廓image = cv2.drawContours(lunkuo_img, filtered_contours, -1, (0, 255, 0), 1) cv2.putText(image, str(num_filtered_contours), (10, 30),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)BGRimage = image[:, :, ::-1]finshPath = "./static/finsh/" + str(maxPhoto) + ".jpg"cv2.imwrite(finshPath, image)return num_filtered_contours

注释:水下物体是用蓝色石头代替的。

五、前端代码

<!DOCTYPE html>
<html>
<head><title>用户界面</title><style>body {display: flex;flex-direction: column;justify-content: center;align-items: center;height: 100vh;margin: 0;}</style><meta http-equiv="refresh" content="5">
</head>
<body><h1>用户界面</h1><img src="{{ image_url }}" alt="Latest Image" width="700" height="700">
</body>
</html>

六、使用流程

第一步:WiFi配置

将ESP32-CAM的WiFi网络名称(SSID)设置为"ESP32",密码设置为"123456789"。

第二步:连接WiFi并启动Web服务器

启动Web服务器,确保它连接到WiFi网络"ESP32"。

打开ESP32-CAM的电源,确保它连接到WiFi网络"ESP32"。

第三步:设备准备就绪指示

启动ESP32-CAM,当ESP32-CAM上的LED慢闪时,表示设备已准备就绪。

第四步:调整LED亮度

双击:快速按两次按钮以调整LED亮度。

调整完成:调整亮度完成后,LED将短暂闪烁一次。

第五步:拍摄图片

单击:按下ESP32-CAM上的按钮,以拍摄一张照片。

成功拍摄:成功拍摄后,LED将短暂闪烁一次。

第六步:查看拍摄的图片

在浏览器中访问以下网址:http://172.20.10.2:5000/send_image 以查看拍摄的图片的处理结果。


总结

本项目实现了在封闭水下环境中计算物体数量的任务,通过深入了解计算机视觉、人工智能和单片机开发领域的核心知识,实现了这一复杂任务。巧妙地将计算机视觉和人工智能的理论应用于实际,通过图像识别、分类和分析等算法,精确计算出水下物体的数量。

在项目的执行过程中,不仅深入研究了相关技术,还通过图像数据的预处理,包括降噪、增强和边缘检测等步骤,优化了数据的特征提取。通过分类算法,能够精确地识别和分类水下物体,最终得出准确的数量计算结果。

此外,对于单片机开发能力也得到了充分提升。能够选择并配置适当的硬件设备,满足项目需求,同时编写高效而可靠的代码,实现了所需功能。掌握了与传感器和其他外部设备的有效通信,确保了图像数据的采集和处理。

总的来说,本项目成功在封闭水下环境中实现了计算水下物体数量的目标。这一项目不仅为我提供了宝贵的经验和技能,深化了对计算机视觉和人工智能领域的理解,还增强了在单片机开发和项目管理方面的能力。这些积累将在未来的研究和工作中增加自信和有能力地面对各种挑战。

这篇关于利用单片机在封闭环境下计算水下物体数量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/766258

相关文章

VScode连接远程Linux服务器环境配置图文教程

《VScode连接远程Linux服务器环境配置图文教程》:本文主要介绍如何安装和配置VSCode,包括安装步骤、环境配置(如汉化包、远程SSH连接)、语言包安装(如C/C++插件)等,文中给出了详... 目录一、安装vscode二、环境配置1.中文汉化包2.安装remote-ssh,用于远程连接2.1安装2

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

mysql-8.0.30压缩包版安装和配置MySQL环境过程

《mysql-8.0.30压缩包版安装和配置MySQL环境过程》该文章介绍了如何在Windows系统中下载、安装和配置MySQL数据库,包括下载地址、解压文件、创建和配置my.ini文件、设置环境变量... 目录压缩包安装配置下载配置环境变量下载和初始化总结压缩包安装配置下载下载地址:https://d

将Python应用部署到生产环境的小技巧分享

《将Python应用部署到生产环境的小技巧分享》文章主要讲述了在将Python应用程序部署到生产环境之前,需要进行的准备工作和最佳实践,包括心态调整、代码审查、测试覆盖率提升、配置文件优化、日志记录完... 目录部署前夜:从开发到生产的心理准备与检查清单环境搭建:打造稳固的应用运行平台自动化流水线:让部署像

gradle安装和环境配置全过程

《gradle安装和环境配置全过程》本文介绍了如何安装和配置Gradle环境,包括下载Gradle、配置环境变量、测试Gradle以及在IntelliJIDEA中配置Gradle... 目录gradle安装和环境配置1 下载GRADLE2 环境变量配置3 测试gradle4 设置gradle初始化文件5 i

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

使用C#如何创建人名或其他物体随机分组

《使用C#如何创建人名或其他物体随机分组》文章描述了一个随机分配人员到多个团队的代码示例,包括将人员列表随机化并根据组数分配到不同组,最后按组号排序显示结果... 目录C#创建人名或其他物体随机分组此示例使用以下代码将人员分配到组代码首先将lstPeople ListBox总结C#创建人名或其他物体随机分组

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo