小程序AI初体验 | 做一款实时识别车辆报价的小程序

个人主页:个人主页
推荐专栏:小程序开发成神之路 --【这是一个为想要入门和进阶小程序开发专门开启的精品专栏!从个人到商业的全套开发教程,实打实的干货分享,确定不来看看?
作者简介从web开发,再到大数据算法,踩过了无数的坑,用心总结经验教训,助你在技术生涯一臂之力!若想获取更多精彩内容,敬请订阅专栏或者关注
⭐️您的小小关注是我持续输出的动力!⭐️


干货内容推荐

入门和进阶小程序开发,不可错误的精彩内容 :

  • 《小程序开发必备功能的吐血整理【个人中心界面样式大全】》
  • 《微信小程序 | 动手实现双十一红包雨》
  • 《微信小程序 | 人脸识别的最终解决方案》
  • 《来接私活吧?小程序接私活必备功能-婚恋交友【附完整代码】》
  • 《吐血整理的几十款小程序登陆界面【附完整代码】》

文章目录

  • 干货内容推荐
  • 一、前言
  • 二、系统架构
    • 2.1 小程序端技术说明
    • 2.2 Flask后端服务
    • 2.3 百度AI SDK的使用
  • 三、小程序UI交互搭建
    • 3.1 开发环境的搭建
    • 3.2 页面元素的编写
    • 3.3 图片接口逻辑实现
  • 四、后台服务端与数据获取
    • 4.1 后台数据接口及调用SDK
    • 4.2 动态爬虫获取数据
  • 五、百度AI平台SDK开通与使用
    • 5.1 创建项目信息,获取到`AppId`,`SecrectId`,`ApiId`
    • 5.2 下载Python SDK并导入项目中
    • 5.3 安装图像识别 Python SDK

一、前言

最近ChatGPT火遍全球,把AI再次推上了高潮。两个月用户就破亿现象,就足以说明这大家对人工智能融入生活的趋势的迫切期待!

国内,作为BAT中的一员的百度,错过了移动互联网时代的浪潮,全身精力投入与AI。这次特意来体会一下百度深耕多年的AI产品的效果究竟能做到什么程度。首先,我们先来感受一下百度的图像识别的能力。为了让这个能力更加具体的表象出来,这次我们要做的是一款结合百度图片识别能力的车辆报价智能识别小程序

为什么会有这样的想法呢?在我们的日常生活中,车是越来越多了,现在买车就像以前买摩托车甚至是买自行车那样普及了。都是四个轮子加一个棚子,除了出行的需求,车也是一种身份的象征!所以,我们这次来做一个可以通过拍照就可以一秒钟识别车辆的价钱的神器!看看是谁在裸泳,带你发现身边的土豪!

二、系统架构

请添加图片描述

2.1 小程序端技术说明

要实现本文中的图片识别功能,主要有两方面的技术难点:

(1)我们要使用合适的系统api,使得用户可以从手机端拍摄照片或者选择相册中的照片上传。

(2)对于用户选择好的图片数据,我们要对其进行编码设计,将其设置到请求体中。

这里的技术栈我们使用:vue语法+uni-app框架

  • 为什么不使用原生语法?
    • 使用微信的原生语法,我们开发出来的程序只能运行在微信平台,如果有一天我们想要迁移到别的平台,我们又要重新按照新平台的语法规则进行重新开发!可复用性基本为零!
    • 不会vue?不用担心!应为微信的原生语法就是基于vue语法的基础上进行封装的而已!只要你会原生开发,上手难度基本为零!如果还是觉得有困难,欢迎阅读本号分享的"vue相关知识",为你上手干活保驾护航!

2.2 Flask后端服务

说到后端服务,这可是这个项目的重头戏了!

小程序AI初体验 | 做一款实时识别车辆报价的小程序_第1张图片

  • (1) 后端服务需要接收来自小程序上传的Image数据,并且将图片以特定的格式传输到百度的SDK api中,从而获取到来自百度服务的识别结果。
  • (2) 除了正常的接收前端的数据以及调用百度图片识别SDK服务的接口之外,在获取到百度服务器所返回的结果之后我们需要根据器结果去差找相应的车辆数据,从而获取到车辆的照片以及最新的报价!

综合以上说的两点,我们可以很明确的知道:一个web容器用来接收数据以及一个爬虫用来查找数据。这需求就变得极其明确了!

那么问题来了:什么语言可以快准狠地实现并且融合这两点呢?毫无疑问,果断选择Python大法

Flask框架 搭配 request爬虫 ---- 直接拿下全场!

2.3 百度AI SDK的使用

百度AI的平台现在越来越完善了,他将大量的ai技术都封装出来做了产品化。所以,我们只需要登录 百度智能云官网,用自己的百度账号开通相应的ai产品即可。
小程序AI初体验 | 做一款实时识别车辆报价的小程序_第2张图片

三、小程序UI交互搭建

3.1 开发环境的搭建

关于小程序的开发环境搭建,也就是分为两个方面:

  • nodejs环境的搭建

    这个步骤是老生常谈的问题了,无非就是那么几步:下载node配置环境变量测试效果

    这一系列的问题基本百度一下都能解决了,但是值得一提的就是,对于那些从windows系统切换到mac系统的用户来说,配置开发环境也是一个不小的挑战。苹果作为生产力神器,建议看一下我整理的: 。让你纵享丝滑!

  • 开发工具的安装和联调

    在确定了使用uniapp框架的基础上,我们可以好不犹豫的选择HBuilderX工具作为我们的开发环境。详细可见:

3.2 页面元素的编写

这一块没啥说的,直接上代码:

<template>
	<view class="content">
		<text class="slogan">拍照、上传你想了解的汽车text>
		<image class="image" :src="imageSrc" mode="widthFix">image>
		<button type="default" class="getBtn" @tap="upload">选择图片button>

		<view class="text-area">
			<text class="title">1text>
			<text class="title">2text>
			<text class="title">3text>
		view>
		<view class="text-area">
			<text class="title">选择图片text>
			<text class="title">AI智能识别text>
			<text class="title">获取报价text>
		view>

		<wyb-popup ref="popup" type="bottom" height="400" width="500" radius="6" :showCloseIcon="true">
		    <view class="popup-content">
		          <hm-cover-card :options="options">hm-cover-card>
		    view>
		wyb-popup>
	view>
template>

3.3 图片接口逻辑实现

这里有两个要点,也是我们在前端开发中经常遇到的问题:

  • 合理利用uni.request()方法!

在这个项目中,我们很清楚,我们需要传输的数据中肯定包含了图片。而图片数据的传输往往是以二进制流的数据形式进行传输,所以我们在数据传输的时候都是将数据的请求类型设置为application/x-www-form-urlencode。很不幸uni.request()方法并不支持该数据格式的传输,所这个时候我们果断翻阅官方文档,经过一番寻找与思考,可以发现:我们可以直接使用uni.uploadFile()方法直接将图片设置为参数即可。


process(image) {
   
	var  imgObj = {'image': image}


	return  uni.uploadFile({
				url: '/api/upload', 
				filePath: image,
				fileType: 'image',
				name: 'image'
	});



}
upload() {
				let _this = this;
				uni.chooseImage({
					count: 1, //默认9
					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
					sourceType: ['album'], //从相册选择
					success: function(res) {
						uni.showLoading({
							title: "AI努力生成中"
						})
						var result = process(res.tempFilePaths[0])
						uni.getImageInfo({
							src: res.tempFilePaths[0],
							success: (path) => {
								pathToBase64(path.path).then(base64 => {
										_this.imageSrc = base64
										_this.options.entryPic = base64
									})
									.catch(err => {
										console.error(err);
									})
							}
						})
						result.then((res)=>{
							console.log('--result--',JSON.parse(res[1].data))
							uni.hideLoading();
							_this.options.title = JSON.parse(res[1].data).name[0]
							_this.options.text = JSON.parse(res[1].data).price[0]
			
							_this.$refs.popup.show() // 显示
						})
					}
				});

			},
  • 处理前端跨域请求!

针对前后端分离的项目而言,抛开实现语言的差异,前端是一个服务,后端又是另外的一个服务。按照浏览器的请求规则,从前端发出的请求数据往往存在需要处理的跨域请求的问题。就像现在这个服务所发生的情况一样,前端的运行地址是:localhost:81,服务端的运行地址是:localhost:8099,尽管两端的域名一致,但是端口并不一致,按照跨域请求的规则,就需要处理这个跨域请求的限制问题。

一般处理跨域请求通常有两种方式(这两种方式的选择需要依赖于特定的业务场景来自我判断):

  • 前端处理:为前端所发出的请求设置代理,让所有的请求都通过前端代理转发,从而避免跨域的问题。【这种方法适用于后端服务地址我们无法修改的情况(如接入什么第三方地址、后端服务已部署好的情况)】
  • 后端处理:后端处理的原理是在前端过来的请求头中将跨域限制的k-v字段设置成允许即可【这种也特别常用,通常在全局添加一个过滤器用于过滤相应请求的请求头即可】。

本项目使用的是前端设置代理的方法,对于vue项目来说,可直接在manifest.json文件中设置如下配置:

"port" : 80,
                        "disableHostCheck" : true,
                        "proxy" : {
                            "/api" : {
                                "target" : "http://127.0.0.1:8099",
                                "changeOrigin" : true,
                                "secure" : false,
				"pathRewrite":{"^/api":""}
                            },
			   "/data" : {
				 "target" : "https://www.autohome.com.cn/grade/carhtml",
				 "changeOrigin" : true,
				   "secure" : false,
				 "pathRewrite":{"^/data":""}
			     }
                        }

四、后台服务端与数据获取

在本项目中,对于后台接口的编写方面,选择的是Python语言,框架使用的是python的轻量级框架Flask.

那么问题来了:对于熟悉前后端开发的小伙伴来说,为什么后端没有选择主流的Java然后搭配SpringBoot框架呢?

  • 就本项目的功能接口来说,主要的功能就只是围绕在:
    • 前端图片数据的接收
    • 获取百度AI接口返回数据
    • 根据百度云获取到的识别结果去车库动态查询到目标车辆的报价信息
  • 按照前两点的功能来说,用SpringBoot框架直接代码生成一下分分钟就搞完了!但是对于第三点功能,就需要想办法如何获取到实时的、完整的车辆信息。这个也是本项目的难点和重头戏! 所以,对于这个需求,可以毫不犹豫地选择爬虫。而Python对于爬虫的实现终究还是比Java来的更快、更准、更狠!
  • 所以我们需要一个可以集成这个爬虫功能的后台接口程序,于是乎我们自然而然的就选择到了Flaskweb框架。通过Flask来写接收请求,然后再通过Request爬虫获取车辆报价信息。

4.1 后台数据接口及调用SDK

from flask import Flask, jsonify, request
import re,os
from aip import AipImageClassify
import RecognizeCar.CrawleCarHome as carhome
from difflib import SequenceMatcher

basedir = os.path.abspath(os.path.dirname(__file__))  # 定义一个根目录 用于保存图片用



""" 你的 APPID AK SK """
APP_ID = '填入你的账号信息'
API_KEY = '填入你的账号信息'
SECRET_KEY = '填入你的账号信息'

client = AipImageClassify(APP_ID, API_KEY, SECRET_KEY)

app = Flask(__name__)

# 使通过jsonify返回的中文显示正常,否则显示为ASCII码
app.config["JSON_AS_ASCII"] = False


@app.route('/upload', methods=['GET', 'POST'])
def editorData():
    # 获取图片文件 name = upload
    img = request.files.get('image')

    # 定义一个图片存放的位置 存放在static下面
    path = basedir + "\\"

    # 图片名称
    imgName = img.filename

    # 图片path和名称组成图片的保存路径
    file_path = path + imgName

    # 保存图片
    img.save(file_path)


    """ 读取图片 """

    def get_file_content(filePath):
        with open(filePath, 'rb') as fp:
            return fp.read()

    image = get_file_content(file_path)

    """ 调用车辆识别 """
    result = client.carDetect(image)

    print(result['result'][0]['name'])
    print(result['result'][0]['name'].replace('_',''))
    recognized_name = result['result'][0]['name'].replace('_','')
    print(single_get_first(result['result'][0]['name'].replace('_','')))

    car_list = carhome.doSpider(single_get_first(result['result'][0]['name'].replace('_','')))

    print(car_list)
    for item in car_list:
        # print(item['name'][0])
        similarity_ratio = SequenceMatcher(None, recognized_name, item['name'][0]).ratio()
        if similarity_ratio > 0.7 :
            print(item)
            return item
    return result



def single_get_first(unicode1):
    str1 = unicode1.encode('gbk')
    try:
        ord(str1)
        return str1.decode('gbk')
    except:
        asc = str1[0] * 256 + str1[1] - 65536
        if asc >= -20319 and asc <= -20284:
            return 'A'
        if asc >= -20283 and asc <= -19776:
            return 'B'
        if asc >= -19775 and asc <= -19219:
            return 'C'
        if asc >= -19218 and asc <= -18711:
            return 'D'
        if asc >= -18710 and asc <= -18527:
            return 'E'
        if asc >= -18526 and asc <= -18240:
            return 'F'
        if asc >= -18239 and asc <= -17923:
            return 'G'
        if asc >= -17922 and asc <= -17418:
            return 'H'
        if asc >= -17417 and asc <= -16475:
            return 'J'
        if asc >= -16474 and asc <= -16213:
            return 'K'
        if asc >= -16212 and asc <= -15641:
            return 'L'
        if asc >= -15640 and asc <= -15166:
            return 'M'
        if asc >= -15165 and asc <= -14923:
            return 'N'
        if asc >= -14922 and asc <= -14915:
            return 'O'
        if asc >= -14914 and asc <= -14631:
            return 'P'
        if asc >= -14630 and asc <= -14150:
            return 'Q'
        if asc >= -14149 and asc <= -14091:
            return 'R'
        if asc >= -14090 and asc <= -13119:
            return 'S'
        if asc >= -13118 and asc <= -12839:
            return 'T'
        if asc >= -12838 and asc <= -12557:
            return 'W'
        if asc >= -12556 and asc <= -11848:
            return 'X'
        if asc >= -11847 and asc <= -11056:
            return 'Y'
        if asc >= -11055 and asc <= -10247:
            return 'Z'
        return ''


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=int("8099"), debug=True)

4.2 动态爬虫获取数据

import requests,json,re
import pandas as pd
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column
from sqlalchemy.types import Integer,String,Date,DateTime,Float,Text
from lxml import etree
import time
from difflib import SequenceMatcher



def doSpider(first_tag):
    url = 'https://www.autohome.com.cn/grade/carhtml/{0}.html'.format(first_tag)
    resp = requests.get(url)
    # html文档
    resp = requests.get(url, headers={
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6776.400 QQBrowser/10.3.2601.400',
    })
    # resp.encoding = 'utf-8'
    rest = resp.text

    html = etree.HTML(rest)
    list = html.xpath('//dd/ul[@class="rank-list-ul"]')
    result = []
    for item in list:
        for el in item:
            name = el.xpath('./h4/a/text()')
            price = el.xpath('./div/a[@class="red"]/text()')
            if len(name) > 0:
                result.append({'name':name,'price':price})

    return result

#
# if __name__ == '__main__':
#     run()

五、百度AI平台SDK开通与使用

5.1 创建项目信息,获取到AppId,SecrectId,ApiId

登录到百度智能云平台,然后选择人工智能产品中的图像识别模块。

小程序AI初体验 | 做一款实时识别车辆报价的小程序_第3张图片
小程序AI初体验 | 做一款实时识别车辆报价的小程序_第4张图片

5.2 下载Python SDK并导入项目中

  • SDK下载地址
    小程序AI初体验 | 做一款实时识别车辆报价的小程序_第5张图片

5.3 安装图像识别 Python SDK

图像识别 Python SDK目录结构

├── README.md
├── aip                   //SDK目录
│   ├── __init__.py       //导出类
│   ├── base.py           //aip基类
│   ├── http.py           //http请求
│   └── imageclassify.py //图像识别
└── setup.py              //setuptools安装

支持Python版本:2.7.+ ,3.+

安装使用Python SDK有如下方式

  • 如果已安装pip,执行pip install baidu-aip即可。
  • 如果已安装setuptools,执行python setup.py install即可。

你可能感兴趣的:(小程序开发成神之路,小程序,人工智能,微信小程序)