家庭IOT监测之摄像头数据上传ONENET

2023-11-18

本篇目标:将摄像头OV7670的照片数据,转换成BMP二进制,上传到ONENET平台,用于远程监测。

材料准备:


摄像头OV7670硬件连接与接口

这里的摄像头OV7670与上一章的一致,详细可以见(家庭IOT监测之摄像头OV7670测试)。


移植摄像头等相关驱动

用keil打开准备材料1的stm32f407_iot工程,往里面添加代码,驱动摄像头OV7670:

  • 将准备材料最终修改中的摄像头驱动文件夹(ov7670)与(rgb2bmp)拷贝到stm32f407_iot标准工程dev文件夹下。
  • 在Manage Project Items添加文件夹ov7670与rgb2bmp,然后添加刚才对应拷贝文件夹下的C文件。
  • 在Options->C/C+±>Include Paths添加dev下复制文件夹ov7670与rgb2bmp的路径。
  • 需要修改ov7670.h与sccb.h文件中对应的IO引脚,修改成自己对应的引脚口,应该用注释标出。
  • 仔细检查ov7670.c与sccb.c文件中的引脚初始化函数,确认相关RESET、PWDN、SCCB等引脚初始化正确;修改dcmi.c的My_DCMI_Init函数中对于DCMI相关引脚的初始化,与自己的引脚对应。
  • 在main.c中添加头文件:
#include "ov7670.h"
#include "dcmi.h"
#include "ov7670test.h"
#include "rgb2bmp.h"
  • 向main函数中添加代码,如下:
	//....
	
    /* WIFI模块IO初始化配置 */
    NET_DEVICE_IO_Init();
	
	/* 摄像头OV7670相关初始化配置 */
	if (OV7670_Init() != 0)    //新添加
	{
		printf("Ov7670 Init Failed.\r\n");
	}
	else
	{
		printf("Ov7670 Init Succeed.\r\n");
#ifdef OV7670_DBG
		OV7670_USART_Init();
#endif
	}
  • 编译通过即可,这样就像上一章一样,移植成功了ov7670的驱动代码,即可使用ov7670摄像头了。

RGB转BMP代码##

在修改之前,先来了解一下,摄像头的数据和BMP文件的数据有哪些不同:

  1. 摄像头数据分很多种,RGB565、RGB555、RGB444、YUV、YCbCr等,这里选取的是RGB565(常用于液晶屏显示直接输出)。RGB565包含16位,如下:
    这里写图片描述
  2. BMP格式数据由几部分组成:
    (1)bmp文件头:共包含有14个字节:
    这里写图片描述
    (2)位图信息头:共包含40个字节;
    这里写图片描述
    (3)调色板:单色,16色,256色包含调色板;16位,24位,32位不包含调色板;
    (4)位图数据;

现在来修改代码:

  • 代码摄像头将获取到的RGB565数据存在了数组camera_buffer[]中,要将数据转换成BMP文件,需要增加bmp文件头和信息头共54字节;
  • 定位文件ov7670.c的17行camera_buffer数组,数组增加54字节,修改成:
uint16_t camera_buffer[PIC_WIDTH*PIC_HEIGHT+27]={0};
  • 定位ov7670.h的23行,同样修改成:
extern uint16_t camera_buffer[PIC_WIDTH*PIC_HEIGHT+27];
  • 修改DMA开始地址与数据长度,往后移54个字节,定位ov7670.c的88行,修改DCMI_DMA_Init传入参数:
DCMI_DMA_Init((uint32_t)&camera_buffer+54,(sizeof(camera_buffer)-54)/4,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Enable);
  • 这样一来数组camera_buffer前54字节放bmp数据头,因为是16位位图,没有调色板,接下来的字节都放ov7670的rgb565数据。
  • 调用rgb2bmp.c中的rgb565tobmp()函数即可将camera_buffer数组修改成二进制bmp文件。

这里贴出RGB2BMP文件的代码:
rgb2bmp.c:

//主函数
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "rgb2bmp.h"


static void RGBtoBMP(char *bmp_buffer, int nWidth, int nHeight, char bits)
{
	BmpHead m_BMPHeader;
	char bfType[2] = { 'B','M' };
	m_BMPHeader.imageSize = bits * nWidth*nHeight + 54;
	m_BMPHeader.blank = 0;
	m_BMPHeader.startPosition = 54;

	memcpy(bmp_buffer, bfType, sizeof(bfType));
	bmp_buffer += sizeof(bfType);
	memcpy(bmp_buffer, &m_BMPHeader.imageSize, sizeof(m_BMPHeader.imageSize));
	bmp_buffer += sizeof(m_BMPHeader.imageSize);
	memcpy(bmp_buffer, &m_BMPHeader.blank, sizeof(m_BMPHeader.blank));
	bmp_buffer += sizeof(m_BMPHeader.blank);
	memcpy(bmp_buffer, &m_BMPHeader.startPosition, sizeof(m_BMPHeader.startPosition));
	bmp_buffer += sizeof(m_BMPHeader.startPosition);

	InfoHead  m_BMPInfoHeader;
	m_BMPInfoHeader.Length = 40;
	m_BMPInfoHeader.width = nWidth;
	m_BMPInfoHeader.height = nHeight;
	m_BMPInfoHeader.colorPlane = 1;
	m_BMPInfoHeader.bitColor = BMP_BITS;
	m_BMPInfoHeader.zipFormat = 0;
	m_BMPInfoHeader.realSize = bits * nWidth*nHeight;
	m_BMPInfoHeader.xPels = 2835;
	m_BMPInfoHeader.yPels = 2835;
	m_BMPInfoHeader.colorUse = 0;
	m_BMPInfoHeader.colorImportant = 0;

	memcpy(bmp_buffer, &m_BMPInfoHeader.Length, sizeof(m_BMPInfoHeader.Length));
	bmp_buffer += sizeof(m_BMPInfoHeader.Length);
	memcpy(bmp_buffer, &m_BMPInfoHeader.width, sizeof(m_BMPInfoHeader.width));
	bmp_buffer += sizeof(m_BMPInfoHeader.width);
	memcpy(bmp_buffer, &m_BMPInfoHeader.height, sizeof(m_BMPInfoHeader.height));
	bmp_buffer += sizeof(m_BMPInfoHeader.height);
	memcpy(bmp_buffer, &m_BMPInfoHeader.colorPlane, sizeof(m_BMPInfoHeader.colorPlane));
	bmp_buffer += sizeof(m_BMPInfoHeader.colorPlane);
	memcpy(bmp_buffer, &m_BMPInfoHeader.bitColor, sizeof(m_BMPInfoHeader.bitColor));
	bmp_buffer += sizeof(m_BMPInfoHeader.bitColor);
	memcpy(bmp_buffer, &m_BMPInfoHeader.zipFormat, sizeof(m_BMPInfoHeader.zipFormat));
	bmp_buffer += sizeof(m_BMPInfoHeader.zipFormat);
	memcpy(bmp_buffer, &m_BMPInfoHeader.realSize, sizeof(m_BMPInfoHeader.realSize));
	bmp_buffer += sizeof(m_BMPInfoHeader.realSize);
	memcpy(bmp_buffer, &m_BMPInfoHeader.xPels, sizeof(m_BMPInfoHeader.xPels));
	bmp_buffer += sizeof(m_BMPInfoHeader.xPels);
	memcpy(bmp_buffer, &m_BMPInfoHeader.yPels, sizeof(m_BMPInfoHeader.yPels));
	bmp_buffer += sizeof(m_BMPInfoHeader.yPels);
	memcpy(bmp_buffer, &m_BMPInfoHeader.colorUse, sizeof(m_BMPInfoHeader.colorUse));
	bmp_buffer += sizeof(m_BMPInfoHeader.colorUse);
	memcpy(bmp_buffer, &m_BMPInfoHeader.colorImportant, sizeof(m_BMPInfoHeader.colorImportant));
	bmp_buffer += sizeof(m_BMPInfoHeader.colorImportant);
}


void rgb565tobmp(char *rgb_buffer, unsigned short nWidth, unsigned short nHeight)
{    
	char bits = BMP_BITS / 8;
	int i = 0;
	int j = 0;
	unsigned char R,G,B;
	unsigned short RGB555,RGB565;
	char *rgb_buff;
	
	rgb_buff = rgb_buffer;
	
	rgb_buffer += 54;
	
	/* RGB565转RGB555 */
	for (i = 0; i < nHeight; i++)
	{
		for (j = 0; j < nWidth; j++)
		{
			/* 读取RGB565 */
			RGB565 = (*(rgb_buffer+1)<<8 | *rgb_buffer);
			/* 分别提取R、G、B数据 */
			B = RGB565 & 0x001f;
			G = (RGB565 >> 6) & 0x001f;
			R = (RGB565 >> 11) & 0x001f;
			/* 转换成RGB555数据 */
			RGB555 = (R << 10) | (G << 5) | (B);
			/* 写入数组 */
			*rgb_buffer = RGB555;
			*(rgb_buffer+1) = RGB555 >> 8;
			rgb_buffer += 2;
		}
	}

	/* 将BMP文件头和信息头写入数组 */
	RGBtoBMP(rgb_buff, nWidth, nHeight, bits);
	
}
   

rgb2bmp.h:

//rgb2bmp.h文件
#include <stdio.h>

#define BMP_BITS 16

typedef unsigned char  BYTE;
typedef unsigned short WORD;
// BMP图像各部分说明如下
/***********
    第一部分    位图文件头
该结构的长度是固定的,为14个字节,各个域的依次如下:
    2byte   :文件类型,必须是0x4d42,即字符串"BM"。
    4byte   :整个文件大小
    4byte   :保留字,为0
    4byte   :从文件头到实际的位图图像数据的偏移字节数。
*************/
typedef struct
{    long imageSize;
    long blank;
    long startPosition;
}BmpHead;

/*********************
第二部分    位图信息头
该结构的长度也是固定的,为40个字节,各个域的依次说明如下:
    4byte   :本结构的长度,值为40
    4byte   :图像的宽度是多少象素。
    4byte   :图像的高度是多少象素。
    2Byte   :必须是1。
    2Byte   :表示颜色时用到的位数,常用的值为1(黑白二色图)、4(16色图)、8(256色图)、24(真彩色图)。
    4byte   :指定位图是否压缩,有效值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS。Windows位图可采用RLE4和RLE8的压缩格式,BI_RGB表示不压缩。
    4byte   :指定实际的位图图像数据占用的字节数,可用以下的公式计算出来:
     图像数据 = Width' * Height * 表示每个象素颜色占用的byte数(即颜色位数/8,24bit图为3,256色为1)
     要注意的是:上述公式中的biWidth'必须是4的整数倍(不是biWidth,而是大于或等于biWidth的最小4的整数倍)。
     如果biCompression为BI_RGB,则该项可能为0。
    4byte   :目标设备的水平分辨率。
    4byte   :目标设备的垂直分辨率。
    4byte   :本图像实际用到的颜色数,如果该值为0,则用到的颜色数为2的(颜色位数)次幂,如颜色位数为8,2^8=256,即256色的位图
    4byte   :指定本图像中重要的颜色数,如果该值为0,则认为所有的颜色都是重要的。
***********************************/
typedef struct
  
{
    long    Length;
    long    width;
    long    height;
    WORD    colorPlane;
    WORD    bitColor;
    long    zipFormat;
    long    realSize;
    long    xPels;
    long    yPels;
    long    colorUse;
    long    colorImportant;
  /*  void show()
  
    {    
        printf("infoHead Length:%dn",Length);
        printf("width&height:%d*%dn",width,height);
        printf("colorPlane:%dn",colorPlane);
        printf("bitColor:%dn",bitColor);
        printf("Compression Format:%dn",zipFormat);
        printf("Image Real Size:%dn",realSize);
        printf("Pels(X,Y):(%d,%d)n",xPels,yPels);
        printf("colorUse:%dn",colorUse);    
        printf("Important Color:%dn",colorImportant);
    }*/
}InfoHead;
/***************************
    第三部分    调色盘结构  颜色表
    对于256色BMP位图,颜色位数为8,需要2^8 = 256个调色盘;
    对于24bitBMP位图,各象素RGB值直接保存在图像数据区,不需要调色盘,不存在调色盘区
    rgbBlue:   该颜色的蓝色分量。
    rgbGreen:  该颜色的绿色分量。
    rgbRed:    该颜色的红色分量。
    rgbReserved:保留值。
************************/
typedef struct
{         BYTE   rgbBlue;
         BYTE   rgbGreen;
         BYTE   rgbRed;
         BYTE   rgbReserved;
      /*   void show(void)
         {
            printf("Mix Plate B,G,R:%d %d %dn",rgbBlue,rgbGreen,rgbRed);
         }*/
}RGBMixPlate;

void rgb565tobmp(char *rgb_buffer, unsigned short nWidth, unsigned short nHeight);


添加代码上传摄像头数据

准备好了转换工作,就可以将BMP传输到ONENET平台上了:

  • 定位net_io.c文件第374行,添加头文件:
#include "dcmi.h"
  • 修改TIM3_IRQHandler中断函数:
void TIM3_IRQHandler(void)
{
	//清中断标识
	TIM_ClearFlag(TIM3, TIM_FLAG_Update);
	//---------------- 中断处理  ------------------//
	if(oneNetInfo.netWork == 1)
	{
		//修改添加判断条件,在上传的照片过程中等待
		if (oneNetInfo.sendData != SEND_TYPE_PICTURE)
		{
			net_send_time++;
		}
		
		if (net_send_time == 1)
		{
			oneNetInfo.sendData = SEND_TYPE_DATA;
			LED2_TOGGLE;
		}
		else if ((net_send_time % 25) == 0)   //每25s发送心跳请求
		{
			oneNetInfo.sendData = SEND_TYPE_HEART;
			LED2_TOGGLE;
		}
		else if (net_send_time == NET_TIME_DELAY/2)
		{
			//修改添加判断条件,只有在空闲的时候在启动摄像头,否则等待
			if (oneNetInfo.sendData == SEND_TYPE_OK)
			{
				//启动摄像头拍照,等待DMA传输
				DCMI_Start();
				LED2_TOGGLE;
			}
		}
		else if (net_send_time == NET_TIME_DELAY)
		{
			net_send_time = 0;
		}
	}
	
	LED1_TOGGLE;
	OneNet_Check_Heart();
}  
  • 定位dcmi.c文件,添加头文件:
#include "onenet.h"
  • 定位dcmi.c文件第78行,在DMA2_Stream1_IRQHandler中断中置位上传图片标志:
oneNetInfo.sendData = SEND_TYPE_PICTURE;
  • 定位main函数,在135行中添加如下函数:
				//....
				
                case SEND_TYPE_PICTURE:
                //新添加
#ifdef OV7670_DBG
					ShanWai_SendCamera(camera_buffer+27, PIC_WIDTH, PIC_HEIGHT);
#endif
					rgb565tobmp((char *)camera_buffer, PIC_WIDTH, PIC_HEIGHT);
					
					oneNetInfo.sendData = OneNet_SendData(FORMAT_TYPE2, NULL, NULL, NULL, 0);
					printf("\r\nOnenet Picture Ready.\r\n");

				//....
  • 定位onenet.c,添加头文件:
#include "ov7670.h"
  • 定位onenet.c第211行,修改替换OneNet_SendData_Picture参入函数如下:
OneNet_SendData_Picture(devid, (char *)camera_buffer, 320*200*2+54);
  • 优化onenet驱动部分函数,定位EdpKit.c第369的EDP_PacketSaveData函数,将第二个参数从int16型改为int32,防止出现图片过大而出现解析问题导致上传不了的问题:
uint8 EDP_PacketSaveData(const int8 *devid, int32 send_len, int8 *type_bin_head, SaveDataType type, EDP_PACKET_STRUCTURE *edpPacket)
  • 同样,在EdpKit.h第112行如上修改成一样:
uint8 EDP_PacketSaveData(const int8 *devid, int32 send_len, int8 *type_bin_head, SaveDataType type, EDP_PACKET_STRUCTURE *edpPacket);
  • 定位EdpKit.c第372行的remain_len变量,同样改为int32型:
	int32 remain_len = 0;
  • 编译,通过后烧写到stm32f407中,观察串口打印,是否上传照片工程:
    这里写图片描述
  • 登录onenet平台查看数据,是否有照片数据上传,如图:

这里写图片描述

这里写图片描述

ps:若是发现上传的照片有垂直,水平颠倒,可以定位ov7670config.h文件第82行,0x1E寄存器:

{0x1e, 0x27},//0x07不翻转;0x17垂直翻转;0x27水平翻转;0x37水平垂直翻转

ONENET修改应用加入照片

进入自己onenet设备的应用管理,编辑:

  • 选择元件库,图片;
  • 属性图片类型选择图片格式的数据流;
  • 数据流选择刚才上传照片的数据流;
  • 调整图片大小合适即可;
  • 点击发布即可;
    在自己的应用主页就可以看到自己的应用数据了,也可以把链接发送给别人查看,如图:
    这里写图片描述

小结:关于摄像头上传数据到ONENET的代码中,有许多可以优化的地方,比如:
(1)可以把摄像头的启动函数DCMI_Start()放在红外外部中断里面,红外一感应到范围里面有人,就用摄像头拍摄下来。
(2)现在用的是WIFI的UART接口,速度只有115200,传输图片需要10s左右之久,所以可以将WIFI改为SPI接口与STM32F407相连,可以大大地加快传输速率。
(3)想过用来传输视频流,但是stm32f407有点不够用,RAM也比较小,如果换成ARM,再用H.264压缩,可以大大降低数据传输压力,再用WIFI视频视频流的传输,初步设想,后期若是视频,再更新博客。

以上移植基本上就完成了,结合以前的数据,就已经把温湿度、红外感应数据以及摄像头照片数据都上传到ONENET平台了,可以达到一个简单的监控的目的了,但只是初步的实现,在调试过程中还存在一些不惹人注意的bug,所以需要耐心多次测试修改,加油,共勉~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

家庭IOT监测之摄像头数据上传ONENET 的相关文章

  • 深圳新政!12大产业将获得大力扶持!

    1月4日 深圳市发布 深圳市数字经济产业创新发展实施方案 2021 2023年 以下简称 实施方案 为未来三年发展指明方向 注 文末可查看 深圳市数字经济产业创新发展实施方案 2021 2023年 原文件 深圳市筛选出十二大细分领域给予重点
  • 物联网LoRa系列-17:LoRa终端Sx1262芯片内部的射频信号放大器

    至此 我们已经拆解了天线是如何发送和接收空中的无线电磁波信号 拆解了无线终端如何对射频前端的高频电信号进行进一步处理的 还拆解了无线终端的发送和接收如何分时复用天线的半双工模式 本篇将进一步拆解无线终端是如何对射频电信号进行进一步的处理 包
  • 量子速写(网站+小程序)

    使用方法非常简单 只需要输入标题 选择文章长短 它就能给你生成一篇AI文章 nbsp nbsp nbsp nbsp 泪奔 它是根据能在网上搜到的相关信息 进行AI组合的 所以不涉及侵权 并且写的合情合理 nbsp nbsp nbsp 加大难
  • DSS部署-11、Spark on Yarn部署

    文章目录 第七部分 Spark on Yarn部署 相关配置 操作记录如下 spark sql e show databases 第七部分 Spark on Yarn部署 相关配置 tar xf spark 2 3 2 bin hadoop
  • 再见,百度网盘!新 60MB/s!

    点击上方卡片 关注回复 青春网盘 即可获得下载链接 近些年 大家苦百度网盘久矣 非会员的限速导致下载速度大多停留再KB为单位 这个问题一直被人吐槽 有关部门规定网盘不许无底线限速 因此百度给出的整改措施是 推出百度网盘青春版 免费用户将享受
  • 基于RFID技术的电力计能表仓储管理系统—铨顺宏

    基于RFID技术的电力计能表仓储管理系统 1 应用背景 电力计量中心是电力行业的电能计量检测机构 承担辖区内电能计量器具安全生命周期管理的职能 包括采购 仓储 检测 配送 安装 运行监测等各个环节 随着城网改造和居民一户一表工作的深入进行
  • 2018中国汽车企业排行榜TOP10

    看排名 懂中国汽车 Aming 汽车行业变化很快 但是从上市车企的情况来看 可以看到具体的财报数字 因而可以知道一个更具体的发展情况 不过这次的排行榜主要针对2018年上半年中国已经上市的汽车企业 特别推出利润排行榜与销量排行榜 同时还有利
  • 5.13 综合案例2.0-火焰检测系统(2.2版本接口有更新)

    综合案例2 0 火焰检测系统 简介 火焰传感器 准备 硬件连接图 代码流程 功能实现 1 物联网平台开发 2 设备端开发 调试 3 物联网应用开发 4 1新建 普通项目 4 2创建 Web应用 4 3页面设计 4 4关联产品 4 5关联数据
  • 阿里平头哥CPU技术生态负责人陈炜:平头哥的发展之路

    整理 巫柔颖 RISC V是近年兴起的一种CPU新架构 因其开放 灵活的特性而逐渐成为半导体行业的热门选择 当前 已有近2500家机构加入RISC V基金会 包括阿里 华为 Google 英特尔 IBM等公司 在阿里宣布平头哥开源玄铁RIS
  • 【车联网原型系统|四】adhoc组网+frp内网穿透

    物联网原型系统导航 车联网原型系统 一 项目介绍 需求分析 概要设计 https blog csdn net weixin 46291251 article details 125807297 车联网原型系统 二 数据库 应用层协议设计 h
  • STM32F4实现SD卡读写

    更多交流欢迎关注作者抖音号 81849645041 目的 熟悉SD卡和SDIO工作原理 掌握SD卡的读写 原理 大多单片机系统都需要大容量存储设备 以存储数据 目前常用的有 U 盘 FLASH 芯片 SD 卡等 他们各有优点 综合比较 最适
  • linux espidf vscode

    安装 根据 https docs espressif com projects esp idf zh CN latest esp32s2 get started linux macos setup html 里的要求安装一些东西 点插件的首
  • 区块链+物联网 BOT

    不可否认 我们的一只脚已经迈入万物智联时代 但另一只脚迈入还存在一定的阻碍 区块链技术的出现将会促进这一进程的发展 智能音响 主人你好 我是小Q 现在是早上08点29分 上班时间要到咯 智能门锁 主人你摔疼我了 你总是这样匆忙 下次赶紧麻溜
  • STM32使用各传感器demo

    先挖个坑 待整理 语音播报部分 1 VS1053语音模块 2 JQ8400语音模块 智能小车部分 3 寻迹模块 4 避障模块 5 舵机驱动 6 超声波模块 7 L298N模块 8 蓝牙JD31模块 兼容HC 05 9 红外模块 10 MPU
  • 【三电平SVPWM学习

    导读 本期对三电平SVPWM的原理和建模做一个简单介绍 并与两电平SVPWM做了一个对比 后面把三电平的SVPWM运用到异步电机直接转矩控制中 看与传统的两电平SVPWM 控制性能是否得到改善 模型可分享 关注公众号 浅谈电机控制 留下邮箱
  • Find My扩展坞|苹果Find My技术与扩展坞结合,智能防丢,全球定位

    扩展坞又称端口复制器 是专为笔记本电脑设计的一种外置设备 通过复制甚至扩展笔记型计算机的端口 可使笔记本电脑与多个配件或外置设备 如电源适配器 网线 鼠标 外置键盘 打印机及外置显示器 方便的一站式连接 随着全球经济复苏 扩展坞市场仍将保持
  • 物联网网关

    物联网网关是 连接物联网设备和互联网的重要桥梁 它负责将物联网设备采集到的数据进行处理 存储和转发 使其能够与云端或其它设备进行通信 物联网网关的作用是实现物联网设备与云端的无缝连接和数据交互 物联网网关功能 数据采集 物联网网关可以从物联
  • 市域治理现代化建设方案(智慧网格解决方案):PPT全文33页,附下载

    关键词 市域治理现代化 智慧网格解决方案 市域治理主要内容 市域社会治理重点内容 市域社会治理现代化 一 市域治理现代化背景 1 城市化进程加速 随着城市化进程的快速推进 城市人口不断增加 城市规模不断扩大 城市治理面临着更加复杂的挑战 2
  • 江河湖泊生态水文监测物联网解决方案

    方案背景 江湖湖泊具有重要的经济效益和生态效益 是重要的资源储备 近年来 各级积极采取措施 加强江河湖泊治理 管理和保护 在防洪 供水 发电 航运 养殖等方面的综合发展 随着纳入管理的江河湖泊等水体越来越多 范围越来越广 很多水污染 非法采
  • 揭秘看不见人的“黑灯工厂”

    你知道吗 未来工厂不需要人也能24小时运转 未来机器能自己配合的天衣无缝 未来工厂连一点灰尘都进不去 未来自研的智能化设备甚至几秒就能生产出一部手机 千万不要惊讶 其实这样的工厂已经在我们的身边 很可能你在元旦买到的一件衣服 一部手机就是

随机推荐

  • 树莓派_超声波传感器_三色LED

    import RPi GPIO as GPIO import time TRIG 26 ECHO 19 GREEN 6 YELLOW 5 RED 13 GPIO setmode GPIO BCM GPIO setwarnings False
  • 仿射系统和非仿射系统的数学定义

    一 非仿射系统 非仿射系统是指系统的输入是以非线性的形式出现的 例如 u 2 sin u 等 12 非仿射系统可以用下面的一般形式表示 x t f x t g x t h u t 其中 x t 是状态变量 u t 是控制输入 f x 和 g
  • Codeforces-1260-E. Tournament贪心

    题目描述 You are organizing a boxing tournament where n boxers will participate n is a power of 2 and your friend is one of
  • 利用celebA数据集训练MTCNN网络

    利用celebA数据集训练MTCNN网络 celebA数据集简介 训练数据的处理 网络和训练 侦测部分 结果展示 有问题可以联系我的邮箱 2487429219 qq com 关于MTCNN网络可以看我上一篇博客 链接 人脸检测算法 mtcn
  • 请用C + +语言写一个生成随机数程序

    include
  • windows系统更改远程桌面端口

    开启远程桌面 我的电脑属性 远程设置 步骤一 在服务器运行窗口中输入 regedit 打开注册表编辑器 步骤二 在注册表HKEY LOCAL MACHINE SYSTEM CurrentControlSet Control Terminal
  • 注解-Annotation Types学习

    前言 注解是JDK5 之后推出的特性 可修饰包 类 方法 变量等 通过在编译 加载和运行时读取其信息 可执行相应的处理 基本原理 java注解类型实质上是一个标记 如 Autowired private TestBean testBean
  • win10家庭中文版开启Hyper-V功能

    问题描述 由于win10家庭中文版是被阉割过的 有些功能就被禁用了 启用和禁用程序中就没有了Hyper V功能 如果想要更多的功能可以将系统升级成为专业版和企业版即可解决 但如果想直接在家庭中文版下创建也是可行 这里有一位大神给出了自己的方
  • LeetCode题解--160. 相交链表

    题目 编写一个程序 找到两个单链表相交的起始节点 例如 下面的两个链表 A a1 a2 c1 c2 c3 B b1 b2 b3 在节点 c1 开始相交 注意 如果两个链表没有交点 返回 null 在返回结果后 两个链表仍须保持原有的结构 可
  • html5中拖放,HTML5中的拖放

    关于HTML5中的拖放 拖放 Drag 和 Drop 是一种常见的特性 即抓取对象以后拖到另一个位置 在 HTML5 中 拖放是标准的组成部分 在HTML5中用户可以使用鼠标选择一个可拖动元素 将元素拖动到一个可放置元素 并通过释放鼠标按钮
  • OpenHarmony dump渲染和合成图层SurfaceBuffer指南

    OpenHarmony dump渲染和合成图层SurfaceBuffer指南 引言 博客停更很久了 提起笔来渐感生疏啊 看来 还是得抽出时间来更新更新啊 好了 感慨也发完了 是时候切入正题了 本篇博客主要以本人在实际项目的开发中 为了定位O
  • 韩信点兵的算法

    秦朝末年 楚汉相争 韩信率兵打仗 某次 他急需点兵迎战 就命士兵布阵三次 命3人一排 多出2名 命5人一排 多出3名 命7人一排 多出2名 后 直言有1073名勇士可击垮敌兵 其神机妙算鼓舞士气 旌旗摇动 大败楚军 首先这个故事的真实性很低
  • Linux下用户的创建与删除

    我们在Linux下创建用户主要有两种方式 adduser和useradd 它们的区别以及主要用法如下 adduser adduser的用法很简单 只需adduser username即可 如下 sudo adduser alvin 这个命令
  • python深入笔记--装饰函数

    装饰函数的参数是被装饰的函数对象 返回原函数对象 装饰的实质语句 hanshu zhuangshi hanshu 第一步 最简单的函数 第二步 对函数进行装饰 hanshu zhuangshi hanshu 定义zhuangshi函数功能
  • Vue中vuex的使用(四)

    四个map方法的使用 1 mapState方法 用于帮助我们映射state中的数据为计算属性 computed 借助mapState生成计算属性 sum school subject 从state中读取数据 对象写法 mapState su
  • RISCV架构单周期CPU设计

    指令选取 R类型指令 31 25 24 20 20 19 15 14 11 7 6 0 funct7 rs2 rs1 funct3 rd opcode 编号 指令 名称 1 add rd rs1 rs2 加 2 and rd rs1 rs2
  • 6个Python童年小游戏,开始敲起来,玩吧!

    你的童年 我的童年好像都一样 谁的童年又没玩过游戏呢 这些小游戏应该只有玩过才会懂吧 虽然程序员敲代码多年 但童心还是一直都在的 今天就分享一些私藏的童年游戏 十几行代码就能进入使用Python开发的小游戏快乐玩耍 1 五子棋 童年游戏不可
  • STM32驱动_旋转编码器EC11(中断触发版本)

    STM32驱动 旋转编码器EC11 中断触发版本 说明 根据示波器测量的真实波形 可以看到 旋转编码器转动一格 实际上只有波形的一个电平变化 并不是输出一个完整周期的波形 中断触发方案 将旋转编码器的A和B两个引脚设置为A下降沿触发 B上升
  • SQL 通配符

    在 SQL 中 通配符与 SQL LIKE 操作符一起使用 SQL 通配符用于搜索表中的数据 在 SQL 中 可使用以下通配符 通配符 描述 替代 0 个或多个字符 替代一个字符 charlist 字符列中的任何单一字符 charlist
  • 家庭IOT监测之摄像头数据上传ONENET

    本篇目标 将摄像头OV7670的照片数据 转换成BMP二进制 上传到ONENET平台 用于远程监测 材料准备 之前移植的温湿度及红外修改工程 温湿度及红外修改工程 继续往里面移植摄像头驱动上传代码 STM32F407最终摄像头上传ONENE