×

TinyML变得简单:图像分类

消耗积分:0 | 格式:zip | 大小:0.00 MB | 2023-07-13

分享资料个

描述

我们越来越多地面临着人工智能 (AI) 革命,正如 Gartner 所说,Edge AI具有非常高的影响潜力,而且现在是这样

poYBAGSBLJOADVU0AABvBP-AhZE651.png
 

在新兴技术的“靶心”中,雷达就是Edge Computer Vision ,而当我们谈到Machine Learning (ML)应用于视觉时,首先想到的就是Image Classification ,一种ML的“Hello World” “!

Seeed Studio 发布了一款经济实惠的新型开发板XIAO ESP32S3 Sense ,它集成了摄像头传感器、数字麦克风和 SD 卡支持。该开发板结合了嵌入式 ML 计算能力和摄影能力,是开始使用 TinyML(智能语音和视觉 AI)的绝佳工具。

XIAO ESP32S3 Sense 主要特点

  • 强大的 MCU 板:集成 ESP32S3 32 位双核 Xtensa 处理器芯片,运行频率高达 240 MHz,安装多个开发端口,支持 Arduino / MicroPython
  • 高级功能:1600*1200分辨率的可拆卸OV2640摄像头传感器,兼容OV5640摄像头传感器,集成一个额外的数字麦克风
  • 精心设计的电源设计:锂电池充电管理能力提供四种功耗模式,允许深度睡眠模式,功耗低至14μA
  • 大内存,更多可能性:提供 8MB PSRAM 和 8MB 闪存,支持 SD 卡插槽,用于外部 32GB FAT 内存
  • 出色的射频性能:支持2.4GHz Wi-Fi和BLE双无线通信,连接U.FL天线支持100m+远程通信
  • 拇指大小的紧凑型设计:21 x 17.5mm,采用 XIAO 的经典外形,适用于可穿戴设备等空间有限的项目
poYBAGSBLJqAUozMAAB9gvSH4v0201.png
 

以下是通用板引出线:

poYBAGSBLKCAdLrGAAX02CeSVq4237.png
 
更多详情请参考Seeed Studio WiKi页面:https://wiki.seeedstudio.com/xiao_esp32s3_getting_started/

在 Arduino IDE 上安装 XIAO ESP32S3 Sense

在 Arduino IDE 上,导航到File > Preferences ,然后填写 URL:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json

在现场 ==>其他 Boards Manager URL

pYYBAGSBLKKAMcX9AABwkgicXvY642.png
 

接下来,打开板管理器。转到Tools > Board > Boards Manager...并输入esp32。选择并安装最新的软件包:

poYBAGSBLKWAdvBRAABsVbfEHcc178.png
 

Tools上,选择 Board ( XIAO ESP32S3 ):

poYBAGSBLKmALQUpAAGoq9WTEX4281.png
 

最后但同样重要的是,选择连接 ESP32S3 的端口。

这就对了!设备应该没问题。让我们做一些测试。

使用 BLINK 测试威廉希尔官方网站 板

XIAO ESP32S3 Sense 有一个连接到 GPIO21 的内置 LED。因此,您可以按原样运行闪烁草图(使用LED_BUILTINArduino 常量)或相应地更改闪烁草图:

#define LED_BUILT_IN 21 

void setup() {
  pinMode(LED_BUILT_IN, OUTPUT); // Set the pin as output
}

// Remember that the pin work with inverted logic
// LOW to Turn on and HIGH to turn off
void loop() {
  digitalWrite(LED_BUILT_IN, LOW); //Turn on
  delay (1000); //Wait 1 sec
  digitalWrite(LED_BUILT_IN, HIGH); //Turn off
  delay (1000); //Wait 1 sec
}
请注意,引脚与反逻辑一起工作:LOW 开启,HIGH 关闭
pYYBAGSBLLaAaJY5ABRvKOc_ieU717.png
 

连接Sense模块(扩展板)

购买时,扩展板与主板分离,但安装扩展板非常简单。需要将扩展​​板上的连接器对准XIAO ESP32S3上的B2B连接器,用力按压,听到“咔哒”一声即表示安装完成。

 

如介绍中所述,扩展板或设备的“感知”部分具有一个 1600x1200 OV2640 摄像头、一个 SD 卡插槽和一个数字麦克风。

麦克风测试

让我们从声音检测开始。转到GitHub 项目并下载草图:XIAOEsp2s3_Mic_Test并在 Arduino IDE 上运行它:

pYYBAGSBLLqANJTgAALrq0CFtik044.png
 

发出声音时,您可以在串行绘图仪上进行验证。

将录制的声音(.wav 音频文件)保存到 microSD 卡。

现在让我们使用板载 SD 卡读卡器来保存 .wav 音频文件。为此,我们需要修复 XIAO PSRAM。

ESP32-S3 在 MCU 芯片上只有几百 KB 的内部 RAM。对于某些用途,ESP32-S3 可以使用与 SPI 闪存芯片并联的最多 16 MB 的外部 PSRAM(伪静态 RAM)可能不够。外部存储器包含在存储器映射中,并且在某些限制下,可以像内部数据 RAM 一样使用。

首先,如下图所示将 SD 卡插入 XIAO(SD 卡应格式化为FAT32 )。

poYBAGSBLL2AVkT0AAEVrr5IjC8657.png
 
  • 下载草图Wav_Record ,您可以在 GitHub 上找到它。
  • 执行代码(Wav Record)需要用到ESP-32芯片的PSRAM功能,所以上传前先开启:Tools>PSRAM: "OPI PSRAM">OPI PSRAM
pYYBAGSBLL-AYo-BAADSZsU93Oo377.png
 
  • 运行代码Wav_Record.ino
  • 该程序仅在用户打开串口监视器后执行一次,录音 20 秒并将录音文件保存到 microSD 卡中,名为“arduino_rec.wav”。
  • 当。。。的时候 ”。” 串口监视器每1秒输出一次,程序执行完毕,可以借助读卡器播放录制的声音文件。
poYBAGSBLMKAIYCtAACCILKpQG0552.png
 

音质非常好!

代码工作原理的解释超出了本教程的范围,但您可以在wiki页面上找到出色的描述。

测试相机

要测试相机,您应该从 GitHub 下载文件夹take_photos_command 该文件夹包含草图 ( .ino) 和两个.h 包含相机详细信息的文件。

  • 运行代码:take_photos_command.ino。打开串行监视器并发送命令“ capture”以捕获图像并将其保存在 SD 卡上:
确认在串行监视器上选择了 [Both NL & CR]。
pYYBAGSBLMmAK0FIAAvCC98uW30523.png
 

这是拍摄照片的示例:

poYBAGSBLMyAMflHAAIG3cAYBbA068.png
 

测试无线网络

XIAO ESP32S3 的差异化因素之一是其 WiFi 功能。所以,让我们测试它的无线电,扫描它周围的 wifi 网络。您可以通过运行板上的代码示例之一来完成。

转到 Arduino IDE 示例并查找WiFI ==> WiFIScan

在串行监视器上,您应该会看到设备范围内的 wifi 网络(SSID 和 RSSI)。这是我在家里得到的:

poYBAGSBLM-ASSscAACe4m8W0QE127.png
 

简单的 WiFi 服务器(打开/关闭 LED)

让我们测试设备充当 WiFi 服务器的能力。我们将在设备上托管一个简单的页面,该页面发送命令以打开和关闭 XIAO 内置 LED。

和以前一样,去 GitHub 下载带有 sketch 的文件夹:SimpleWiFiServer

在运行草图之前,您应该输入您的网络凭据:

const char* ssid     = "Your credentials here";
const char* password = "Your credentials here";

您可以使用串行监视器监视您的服务器如何工作。

pYYBAGSBLNKAVi6SAAEq8TBr5rI652.png
 

获取 IP 地址并将其输入浏览器:

pYYBAGSBLNSAGEA7AABkZ4N3MXg352.png
 

您将看到一个页面,其中包含可以打开和关闭 XIAO 内置 LED 的链接。让我们将相机拍摄的图像传输到网页:

从 GitHub 下载包含代码的文件夹:XIAO-ESP32S3-Streeming_Video.ino。

请记住,该文件夹不仅包含 .ino 文件,还包含一些处理相机所必需的 .h 文件。

输入您的凭据并运行草图。在串行监视器上,您可以找到要在浏览器中输入的页面地址:

poYBAGSBLNeAT5eNAAB6QwB4it0896.png
 

在浏览器上打开页面(等待几秒钟以开始流式传输)。就是这样。

poYBAGSBLNyALScfAAOaarnJ1eM986.png
 

当您定位相机以捕获 ML 项目的数据集(例如,使用代码“take_phots_commands.ino”)时,简化相机“看到”的内容可能很重要。

当然,我们可以同时做这两件事,在页面上显示相机所看到的内容,并发送一个命令来捕获图像并将其保存在 SD 卡上。为此,您可以使用代码 Camera_HTTP_Server_STA,该文件夹可以从 GitHub 下载。

pYYBAGSBLN-AGOImAAIwiNeiqxU890.png
 

该程序将执行以下任务:

  • 将相机设置为 JPEG 输出模式。
  • 创建网页(例如==> http://192.168.4.119//)。正确的地址将显示在串行监视器上。
  • 如果是 server.on ("/capture", HTTP_GET, serverCapture),程序会拍摄照片并将其发送到 Web。
  • 可以使用 [ROTATE] 按钮在网页上旋转图像
  • [CAPTURE]命令只会在网页上预览图片,在串口监视器上显示图片大小
  • [SAVE] 命令会将图像保存在 SD 卡上,同时在网络上显示该图像。
  • 保存的图像将遵循顺序命名(image1.jpg,image2.jpg。
poYBAGSBLOOAGYCgAACglbC_lkw985.png
 
该程序可用于图像分类项目的图像数据集捕获。

检查代码;这将更容易理解相机的工作原理。此代码是基于伟大的 Rui Santos 教程:ESP32-CAM 在 Web 服务器中拍照和显示而开发的,我邀请大家访问。

水果与蔬菜 - TinyML 图像分类项目

现在我们有一个嵌入式相机在运行,是时候尝试图像分类了。为了比较动机,我将复制为与旧 ESP2-CAM 一起使用而开发的相同图像分类项目:

ESP32-CAM:TinyML 图像分类——水果与蔬菜

我们项目的整体思路是训练模型并在 XIAO ESP32S3 Sense 上进行推理。对于训练,我们应该找到一些数据(实际上是大量数据!)。

但首先,我们需要一个目标!我们要分类什么?

使用TinyML,一组与嵌入式设备上的机器学习推理相关的技术,由于限制(在这种情况下主要是内存),我们应该将分类限制为三或四类。我们将区分苹果香蕉土豆(您可以尝试其他类别)

因此,让我们找到一个包含这些类别图像的特定数据集。Kaggle 是一个好的开始:

https://www.kaggle.com/kritikseth/fruit-and-vegetable-image-recognition

该数据集包含以下食品的图像:

  • 水果-香蕉、苹果、梨、葡萄、橙子、奇异果、西瓜、石榴、菠萝、芒果。
  • 蔬菜- 黄瓜、胡萝卜、辣椒、洋葱、马铃薯、柠檬、番茄、萝卜、甜菜根、卷心菜、生菜、菠菜、大豆、花椰菜、灯笼椒、辣椒、萝卜、玉米、甜玉米、红薯、红辣椒、墨西哥辣椒、生姜、 大蒜、 豌豆、 茄子。

每个类别分为训练(100 张图像)、测试(10 张图像)和验证(10 张图像)。

  • 从 Kaggle 网站将数据集下载到您的计算机。
或者,您可以添加一些来自家庭厨房的香蕉、苹果和土豆的新鲜照片,例如,使用上一节中讨论的草图。

使用 Edge Impulse Studio 训练模型

我们将使用 Edge Impulse Studio 来训练我们的模型。Edge Impulse是领先的边缘设备机器学习开发平台。

在 Edge Impulse 输入您的帐户凭据(或创建一个免费帐户)。接下来,创建一个新项目:

pYYBAGSBLO2ALskMAAGpM2bH1MY825.png
 

数据采集

接下来,在该UPLOAD DATA部分,从您的计算机上传所选类别的文件:

poYBAGSBLPGAJo4gAACbEYxmjGU348.png
 

您现在应该拥有训练数据集,分为三类数据:

pYYBAGSBLPSAZ-aVAADKzDlnTBc806.png
 
您可以上传额外的数据以进行进一步的模型测试或拆分训练数据。我将保留原样,尽可能使用大部分数据。

冲量设计

脉冲获取原始数据(在本例中为图像),提取特征(调整图片大小),然后使用学习块对新数据进行分类。

如前所述,对图像进行分类是深度学习最常见的用途,但要完成这项任务需要大量数据。每个类别我们有大约 90 张图像。这个数量够吗?一点也不!我们将需要数千张图像来“教授或建模”以区分苹果和香蕉。但是,我们可以通过使用数千张图像重新训练之前训练过的模型来解决这个问题。我们称这种技术为“迁移学习”(TL)。

pYYBAGSBLPeAdufiAAEJZ5trvIM494.png
 

借助 TL,我们可以根据我们的数据微调预训练图像分类模型,即使在相对较小的图像数据集(我们的案例)中也能表现良好。

因此,从原始图像开始,我们将调整它们的大小 (96x96) 像素,然后将它们提供给我们的迁移学习块:

poYBAGSBLPuATWY5AACzZOw8mQI732.png
 

预处理(特征生成)

除了调整图像大小,我们应该将它们改为灰度以保持实际的 RGB 颜色深度。这样做,我们的每个数据样本都将具有 9 维、216 个特征 (96x96x1)。保持 RGB,这个维度会大三倍。使用灰度有助于减少推理所需的最终内存量。

poYBAGSBLP6AQdKLAAChy7GPqkg301.png
 

不要忘记“保存参数”。这将生成要在训练中使用的特征。

培训(迁移学习和数据增强)

2007 年,谷歌推出了MobileNetV1,这是一个通用计算机视觉神经网络系列,专为移动设备而设计,支持分类、检测等。MobileNet 是小型、低延迟、低功耗模型,经过参数化以满足各种用例的资源限制。

尽管基本 MobileNet 架构已经很小并且延迟很低,但很多时候,特定的用例或应用程序可能需要模型更小和更快。MobileNet 引入了一个称为宽度乘数的简单参数 α (alpha) 来构建这些更小且计算成本更低的模型。宽度乘数 α 的作用是在每一层均匀地细化网络。

Edge Impulse Studio 具有可用的 MobileNet V1(96x96 图像)和 V2(96x96 和 160x160 图像),具有多个不同的α值(从 0.05 到 1.0)。例如,您将使用 V2、160x160 图像和 α=1.0 获得最高准确度。当然,需要权衡取舍。精度越高,运行模型所需的内存就越多(大约 1.3M RAM 和 2.6M ROM),这意味着更多的延迟。

在MobileNet V1和 α=0.10(大约 53.2K RAM 和 101K ROM)的另一个极端情况下,将获得更小的占用空间

当我们第一次发布这个在 ESP32-CAM 上运行的项目时,我们停留在可能性的较低端,这保证了推理具有较小的延迟但不具有高精度。对于第一遍,我们将保留此模型设计(MobileNet V1和 α=0.10)。

与深度学习一起使用的另一个重要技术是数据增强数据增强是一种可以帮助提高机器学习模型准确性的方法,可以创建额外的人工数据。数据增强系统在训练过程中对训练数据进行小的随机更改(例如翻转、裁剪或旋转图像)。

在底层,您可以在这里看到 Edge Impulse 如何对您的数据实施数据增强策略:

# Implements the data augmentation policy
def augment_image(image, label):
    # Flips the image randomly
    image = tf.image.random_flip_left_right(image)

    # Increase the image size, then randomly crop it down to
    # the original dimensions
    resize_factor = random.uniform(1, 1.2)
    new_height = math.floor(resize_factor * INPUT_SHAPE[0])
    new_width = math.floor(resize_factor * INPUT_SHAPE[1])
    image = tf.image.resize_with_crop_or_pad(image, new_height, new_width)
    image = tf.image.random_crop(image, size=INPUT_SHAPE)

    # Vary the brightness of the image
    image = tf.image.random_brightness(image, max_delta=0.2)

    return image, label

在训练期间接触这些变化有助于防止您的模型通过“记住”训练数据中的表面线索来走捷径,这意味着它可以更好地反映数据集中深层的潜在模式。

我们模型的最后一层将有 16 个神经元和 10% 的 dropout 以防止过度拟合。这是训练输出:

pYYBAGSBLQCANeSuAACU6MqNCm4206.png
 

结果不是很好。该模型达到了 77% 左右的准确率,但预计在推理过程中使用的 RAM 量相对较小(约 60 KB),这非常好。

部署

经过训练的模型将部署为 .zip Arduino 库:

poYBAGSBLQOAZlydAACY_ljXcB4419.png
 

打开您的 Arduino IDE,在Sketch 下,转到Include Library添加 .ZIP Library。选择您从 Edge Impulse Studio 下载的文件,就是这样!

pYYBAGSBLQaAUN3QAADvijSIC9Q969.png
 

在 Arduino IDE 的示例选项卡,您应该在项目名称下找到草图代码。

pYYBAGSBLQqAQKQ7AAGf06gf6F4205.png
 

打开静态缓冲区示例:

pYYBAGSBLQ2Ae3PCAAFhBNIFE2E678.png
 

您可以看到第一行代码正是调用一个库,其中包含在您的设备上运行推理所需的所有必要内容。

#include 

当然,这是一个通用代码(一个“模板”),它只获取一个原始数据样本(存储在变量中:features = {} 并运行分类器,进行推理。结果显示在串行监视器上。

我们应该从相机中获取样本(图像)并对其进行预处理(将大小调整为 96x96,转换为灰度,并将其展平)。这将是我们模型的输入张量。输出张量将是一个具有三个值(标签)的向量,显示每个类别的概率。

pYYBAGSBLQ-AWf15AAB96jSG6to695.png
 

返回您的项目(选项卡图像),复制原始数据示例之一:

poYBAGSBLROAUY1-AAIYrlxQ1Sw020.png
 

9、将216个特征复制到剪贴板。这是输入张量(96x96x1 的扁平图像),在本例中为香蕉。超过此输入张量 features[] = {0xb2d77b, 0xb5d687, 0xd8e8c0, 0xeaecba, 0xc2cf67, ...}

poYBAGSBLRaAIJ65AAD83HHOMpY905.png
 

注意:Edge Impulse在其 SDK 中包含ESP NN 库,其中包含针对各种 Espressif 芯片优化的 ​​NN(神经网络)函数。在本教程发布(5 月 2 日)之前,ESP NN 无法与 ESP32S3 (Arduino IDE) 一起使用。

如果您编译代码并遇到错误,则有必要修复它。EI 建议关闭 ESP NN 加速。为此,ei_classifier_config.h在导出的 Arduino 库文件夹中找到: /scr/edge-impulse-sdk/classifier/:

poYBAGSBLRmAImQfAAEao8V24O4165.png
 

找到带有 的行#define EI_CLASSIFIER_TFLITE_ENABLE_ESP_NN 1,并将其从 1 更改为 0:

poYBAGSBLR-AT0BGAAEkV0h8wbM263.png
 

现在,在运行推理时,您应该得到“banana”的最高分。

pYYBAGSBLSOAZ3KlAACz5jwbk74829.png
 

好消息!我们的设备进行推理,发现输入图像是香蕉。这是比 ESP32 CAM(525 毫秒延迟)更好的结果。

现在,我们应该结合摄像头并对图像进行实时分类。

转到 Arduino IDE 示例并从您的项目下载草图 esp32_camera:

poYBAGSBLSaAJalpAABvcwIuy5Y279.png
 

您应该根据与我们的模型相关的数据更改第 32 行到第 75 行,它们定义了相机模型和引脚:

pYYBAGSBLSmAGu8rAACRmvlOaCU469.png
 

修改后的草图可以从 GitHub 下载:xiao_esp32s3_camera

请注意,您可以选择将引脚保留为 ah 文件,就像我们在前几节中所做的那样。

将代码上传到您的 XIAO ESP32S3 Sense,您应该就可以开始对水果和蔬菜进行分类了!您可以在串行监视器上检查结果。

测试模型(推理)

poYBAGSBLS2AP8SEAAOnArpXIJU262.jpg
 

使用相机拍摄照片,分类结果将显示在串口监视器上:

pYYBAGSBLTCAY20oAACtdqArdmE112.png
 

其他测试:

 
 
 
pYYBAGSBLTiAL_TKAAlFsGY7iPM934.png
 
1 / 3
 

使用更大的模型进行测试

现在,让我们转到模型尺寸的另一侧。让我们选择一个 MobilinetV2 96x96 0.35,输入 RGB 图像。

poYBAGSBLTuAcAFxAAGqNeLLs2w132.png
 

即使使用更大的模型,准确性也不好,最糟糕的是,运行模型所需的内存量增加了五倍,延迟增加了七倍。因此,为了让我们的模型更好,我们可能需要训练更多的图像。

即使我们的模型没有改进,让我们测试一下 XIAO 是否可以处理这么大的模型。我们将使用静态缓冲区草图进行简单的推理测试。

poYBAGSBLT6AaiuBAACrDtzqb-c797.png
 

结果是肯定的!内存在这里不是问题;延迟是!在实际测试中看到,XIAO 花费了将近 2.5 秒来执行推理(与之前的 318 毫秒相比)。

可选择使用 ESP-NN 加速 [2013 年 5 月 19 日更新]

尽管 Edge Impulse 尚未发布使用加速器的 ESP32S3 SDK,但多亏了Dmitry Maslov, 我们可以为 ESP32-S3 恢复和修复 ESP NN 的装配优化。这个解决方案还不是官方的,因为一旦他们解决了与其他板的冲突,EI 就会将它包含在 EI SDK 中。

目前,这仅适用于非 EON 版本。因此,如果在生成库时启用了 EON 编译器,则应重新部署模型。

pYYBAGSBLUGAIMXAAAGgnfgXWMo042.png
 

同时,你可以从项目的GitHub上下载一个初步版本,解压,将
src/edge-impulse-sdk/porting/espressif/ESP-NN,你的Arduino库文件夹下的ESP NN文件夹替换为:

poYBAGSBLUSAVdyxAAB8_KatwHs112.png
 

然后编译草图。替换文件夹后重新启动 IDE 可能会有所帮助。

使用 MobilinetV2 96x96 0.35 进行推理,将 RGB 图像作为输入,延迟从 2,383 毫秒减少到 219 毫秒,减少了十倍以上!

 
 
 
poYBAGSBLUeAU2TdAACj8UihduE056.png
 
1 / 2
 

在我的测试中,此选项适用于 MobileNet V2 但不适用于 V1。因此,我再次训练模型,使用最小版本的 MobileNet V2,alpha 为 0.05。

poYBAGSBLUuAHMwTAAGvzha0Wlw461.png
 
请注意,以 480MHz 时钟运行的 Arduino Portenta(ou Nicla)的估计延迟为 45ms。

部署模型,并应用修复,替换 ESP-NN 文件夹,如前所述,我得到的推断只有 135 毫秒,记得 XIAO 运行的时钟是 Portenta/Nicla 使用的时钟的一半(240MHz):

pYYBAGSBLU6Af8SZAAFAJXhknLU878.png
 

结论

XIAO ESP32S3 Sense 是一款非常灵活、价格低廉且易于编程的设备。该项目证明了 TinyML 的潜力。内存不是问题;该设备可以处理许多后处理任务,包括通信。但是你应该考虑到高延迟(没有 ESP NN 加速器)会限制一些应用程序,尽管 XIAO 比 ESP32-CAM 快 50%。

在我的 GitHub 存储库中,您会找到最新版本的代码:XIAO-ESP32S3-Sense。

一如既往,我希望这个项目可以帮助其他人在令人兴奋的人工智能、电子和物联网世界中找到自己的出路!

poYBAGNVlOKAQp0tAABnO-FoD-w048.png
 

链接:MJRoBot.org

来自世界南方的问候!

在我的下一个项目见!

谢谢

马塞洛


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'TinyML变得简单:图像分类',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);