最近,在一个论坛交流会上, 有嘉宾提出自己运营多年的微信小程序商城经常收到用户反馈:自己在逛街时候发现别人穿的好看的衣服,很难通过关键字定位到具体的商品,如果能拍照定位相关的商品就好了,问目前小程序里面能否实现这样的功能。作为一名软件开发者, 日常网购也有类似的体会。如果能在小程序里集成商品搜索的功能,就能大大提升用户的体验,嘉宾的问题引发我极大的兴趣。

在调研过程中,发现腾讯云图像分析的图像搜索产品可以基于输入图片,智能识别图片中的商品主体,在自建图片库中搜索相同或相似的商品图片,并给出相似度打分。如果输入检索的图片包含服饰类商品,可智能识别上衣、下装、裙装、鞋、包、配饰等多种服饰的类别、颜色以及其他特征属性,实现电商场景下的以图搜图。

接下来 ,将详细分享一下我是如何在小程序里实现商品搜索的。

一、准备工作

1.1明确目标

在小程序里,通过输入商品图片来定位相似的商品图,类似于下面这个:

1.2了解图像搜索

在开始使用之前,还是得对我即将要用的产品进行一个比较详细的了解。

官网文档介绍:

接口文档:

1.3开通图像分析服务

接下来就可以按照官网文档的指引在腾讯云官网开通图像分析服务:

开通服务后 ,创建图片和检索图片分别会发放一万次免费资源包, 可以在资源包管理页面查看使用情况:

二、开发流程

2.1获取个人密钥

在腾讯云官网访问管理页面, 新建个人密钥:

2.2在线调试

下面通过在线调试的方式简单的实现拍立淘的功能。

(1)图库类型选择

首先查看图像搜索的文档,我们选择商品图像搜索的服务类型。

(2)创建图库

创建图片库,指定商品图像搜索, 腾讯云官网提供了在线调用 API Explorer 工具,方便我们可视化调用。

(3)图片入库

创建图片, 将商品图片入库到指定图库中,返回值中包含了主体位置信息。

(4)商品搜索

检索图片, 指定商品图,在图库中进行检索 ,获取相似或者相同的商品图, 返回结果中包含了与输入图类似的商品ID。

这样就基本上演示出了商品搜索的过程,对于使用而言,可以对输入的参数进行一些微调,满足更多的要求。

2.3使用SDK调用

(1)文档介绍

正式接入的话,需要集成腾讯云官网上提供的SDK。 在文档的最下方,提供了多个语言的SDK,可以根据自己熟悉的语言进行接入。

(2)示例

以go语言为例,演示下如何使用。

第一步: 安装基础包:

go get -v -u github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common

安装图像分析依赖:

go get -v -u github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tiia

第二步: 实现调用,以创建图库为例。

credential := common.NewCredential(***, ***)
clientProfile := profile.NewClientProfile()
clientProfile.HttpProfile.Endpoint = "tiia.tencentcloudapi.com"cli, err := tiia.NewClient(credential, regions.Guangzhou, clientProfile)
if err != nil {panic(err)
}
//实例化一个请求结构
req := tiia.NewCreateGroupRequest()
//对请求参数进行赋值
req.GroupId = common.StringPtr("groupId")
req.GroupName = common.StringPtr("groupName")
req.Brief = common.StringPtr("brief")
req.MaxCapacity = common.Uint64Ptr(uint64(100))
req.MaxQps = common.Uint64Ptr(uint64(10))
req.GroupType = common.Uint64Ptr(uint64(5))
//调用请求
resp, err := cli.CreateGroup(req)
if err != nil {return
}

三、小程序实现商品搜索

上面介绍了图像搜索的基本能力,如何应用商品搜索能力,来实现拍立淘的效果呢,接下来以小程序为例,来演示一个简单的应用:

3.1构建底库

根据上述文档, 我们在服务端使用sdk来初始化图片库,然后通过小程序端来访问,这里不再赘述。

1. 使用2.1申请的secretID,secretkey来创建图库。

2. 商品图入库。

3.2构建小程序

index.js

const app = getApp()Page({data: {urls: [],inputValue: "图片URL",buttonStatus: false,category: ['Jacket', 'dress', 'trousers', 'bag', 'shoe', 'accessories'],motto: 'Hello World',userInfo: {},hasUserInfo: false,canIUse: wx.canIUse('button.open-type.getUserInfo'),canIUseGetUserProfile: false,canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // 如需尝试获取用户信息可改为false},// 事件处理函数bindViewTap() {wx.navigateTo({url: '../logs/logs'})},onLoad() {if (wx.getUserProfile) {this.setData({canIUseGetUserProfile: true})}},getUserProfile(e) { // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗wx.getUserProfile({desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写success: (res) => {console.log(res)this.setData({userInfo: res.userInfo,hasUserInfo: true})}})},getUserInfo(e) {// 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息console.log(e)this.setData({userInfo: e.detail.userInfo,hasUserInfo: true})},isUrl (url) {var urlRegExp=/^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\*\+,;=.]+$/;if(urlRegExp.test(url)){return true;}else{return false;}},imageSearch() {var that = thiswx.request({url: 'http://****/search',data: {"GroupId": "***","ImageUrl": this.data.inputValue},method: "POST",header: {'Content-Type': "application/json"},success (res) {if (res.data == null) {wx.showToast({icon: "error",title: '请求失败',})return}console.log(res.data)that.setData({urls: res.data.Urls,object: res.data.Object})that.drawInputImage()},fail(res) {wx.showToast({icon: "error",title: '请求失败',})}})},drawInputImage: function() {var that = this;wx.downloadFile({url: that.data.inputValue,success: function(res) {var imagePath = res.tempFilePath// 绘制wx.getImageInfo({src: imagePath,success: function(res) {wx.createSelectorQuery().select('#input_canvas') // 在 WXML 中填入的 id.fields({ node: true, size: true }).exec((r) => {// Canvas 对象const canvas = r[0].node// 渲染上下文const ctx = canvas.getContext('2d')// Canvas 画布的实际绘制宽高 const width = r[0].widthconst height = r[0].height// 初始化画布大小const dpr = wx.getWindowInfo().pixelRatiocanvas.width = width * dprcanvas.height = height * dprctx.scale(dpr, dpr)// 清空画布ctx.clearRect(0, 0, width, height)let radio = height / res.heightconsole.log("radio:", radio)const img = canvas.createImage()var x = width / 2 - (res.width * radio / 2)img.src = imagePathimg.onload = function() {ctx.drawImage(img, x, 0, res.width * radio, res.height * radio)var allBox = that.data.object.AllBoxctx.fillStyle = 'rgba(247, 15, 2, 0.7)';for (var i in allBox) {if (allBox[i].Rect.X == that.data.object.Box.Rect.X && allBox[i].Rect.Y == that.data.object.Box.Rect.Y) {continue}ctx.fillRect(x + (allBox[i].Rect.X * radio), allBox[i].Rect.Y * radio, allBox[i].Rect.Width * radio,allBox[i].Rect.Height * radio);}// 绘制主体ctx.fillStyle = 'rgba(159, 255, 125, 0.7)'; //rgba(0, 0, 200, 0.5)ctx.fillRect(x + (that.data.object.Box.Rect.X * radio), that.data.object.Box.Rect.Y * radio, that.data.object.Box.Rect.Width * radio,that.data.object.Box.Rect.Height * radio);console.log(that.data.object.AllBox)// 绘制文字背景let text = `${that.data.category[that.data.object.CategoryId]} ${that.data.object.Box.Score}`ctx.fillStyle = '#221329'ctx.fillRect(x + (that.data.object.Box.Rect.X * radio), that.data.object.Box.Rect.Y * radio, that.data.object.Box.Rect.Width * radio, 15)// 绘制文字ctx.fillStyle = '#fcfafc'console.log(that.data.category[that.data.object.CategoryId])ctx.fillText(text, x + (that.data.object.Box.Rect.X * radio), that.data.object.Box.Rect.Y * radio + 10) }          })}})}})},handlerInput(e) {console.log(e)this.setData({inputValue: e.detail.value})},handlerSearch(e) {console.log(this.data.inputValue)if (!this.isUrl(this.data.inputValue)) {console.log("error url: ", this.data.inputValue)wx.showToast({icon: "error",title: '请输入正确url',})return }this.setData({buttonStatus: true})this.imageSearch()this.setData({buttonStatus: false})},handlerInputImage(e) {console.log(e)}
})

index.wxss:

/**index.wxss**/
.userinfo {display: flex;flex-direction: column;align-items: center;color: #aaa;
}.userinfo-avatar {overflow: hidden;width: 128rpx;height: 128rpx;margin: 20rpx;border-radius: 50%;
}.usermotto {margin-top: 200px;
}page {background: rgb(255, 255, 255);
}
.page-section-spacing {width: 100%;
}
.container {padding: 0;
}.button_container {margin-top: 600rpx;
}
.flex-wrp{margin-top: 60rpx;margin: auto;width: 90%;overflow: hidden;
}.form-item {margin-bottom: 10px;margin-top: 10px;width: 90%;overflow: hidden;
}
.flex-item{float: left;width: 300rpx;height: 400rpx;font-size: 26rpx;margin: 10rpx 10rpx 0rpx 20rpx;overflow: hidden;
}
.flex-item-V{margin: 0 auto;width: 300rpx;height: 200rpx;
}.input {width: 75%;float: left;height: 36px;border: 1px solid #ddd;
}.button {float: right;height: 36px;    background: rgb(236, 111, 61);color: white;
}.view_line {width: 96%;height: 50rpx;display: flex;flex-direction: row;align-items: center;justify-content: left;margin: 0rpx 2% 0rpx 2%;
}.view_line view {width: 75%;height: 2rpx;background: linear-gradient(to right,#706f70, #706f70);
}.text_line {font-size: 25rpx;color: rgb(66, 66, 66);margin: 0rpx 2% 0rpx 2%;
}
.image {width: 100%;
}
.image image {width: 100%;background-size: auto 100%;background-repeat: no-repeat;
}

index.wxml:

<view class="container"><div class="form-item"><input placeholder=" 商品URL" class="input" bindinput="handlerInput" /><button class="button"  loading="{{buttonStatus}}" bindtap="handlerSearch" size="mini">搜索 </button></div><view class="view_line"><text class="text_line">输入图片</text><view></view></view><canvastype="2d"id="input_canvas"style="background:rgb(228, 228, 225); width: 360px; height: 240px;"></canvas><view class="view_line"><text class="text_line">搜索结果</text><view></view></view><view class="page-section-spacing"><view  class="flex-wrp" style="flex-direction:row;"><view wx:for="{{urls}}" class="flex-item"><view class="image"> <image mode="aspectFit" style="background-color: #eeeeee;" src="{{item}}"></image></view></view></view> </view></view>

编译即可:

3.3构建运行

输入商品图,图搜服务会进行主体识别,然后再进行相似图搜索,可以看到效果如下:

如果不做主体识别,可能搜不到我们想要的结果,例如,我们想要这个墨镜,但是不开主体识别的话可能会定位到衣服,导致没有结果:

看下图搜主体识别的文档介绍:

118px使用商品图像搜索默认会开启主体识别,涉及到以下两个参数:

默认情况下主体识别是打开的,服务会针对输入图中的服饰进行主体位置识别,以实现更好的搜索效果,如下:

按照上述主体识别的描述,指定下配饰类目,服务会定位到墨镜的位置,就可以搜索到预期的商品了:

到这一步就实现了小程序中商品搜索的基本功能,涉及到商品搜索的场景,都可以参考下。后面给朋友展示了小程序demo, 体验下来,使用效果相当满意。

3.4查看调用量

在后续观察中,可以在腾讯云官网, 进入到图像分析控制台,可以查看最近的调用情况。

了解更多图像搜索功能:https://cloud.tencent.com/product/imagesearch

最佳实践|用腾讯云AI图像搜索打造属于自己的拍立淘相关推荐

  1. 最佳实践 | 用腾讯云AI语音识别零基础实现小程序语音输入法

    先回顾下,生活.工作中你使用过哪些语音识别相关的产品或者服务? 培训/考试相关的小程序,使用语音识别来判断回答是否正确: 英语口语练习的小程序,使用语音识别来打分: 你画我猜类的小程序,使用语音识别来 ...

  2. 最佳实践 | 用腾讯云AI人像变换给自己一次“跨越年龄的体验”

    互联网时代,日新月异的技术更迭让大众的娱乐方式变得更加多元化.越来越多线上娱乐体验成为新潮流,不少公司各出奇招,推出了AI人像特效.VR游景点.可交互影视剧.元宇宙等:人们花在线上娱乐体验的时间越来越 ...

  3. 微信小程序云开发调用 腾讯云AI 图像标签

    本白菜在开发微信小程序调用腾讯云AI图像标签产品时,遇到了问题,自己琢磨了三天,搜遍了能搜的东西,还是没有解决.下边记录一下 调用过程 1.首先进入https://cloud.tencent.com/ ...

  4. 最佳实践 | 用腾讯云慧眼人脸核身为诚信考试保驾护航

    点击参与:腾讯云AI用户实践有奖征稿活动! 2020年新冠疫情爆发后,疫情之下的考试在各国均受到不同程度的影响,"延期"."取消"."补考" ...

  5. 最佳实践 | 用腾讯云智能语音打造智能对话机器人

    在AI技术的推动下,智能对话机器人逐渐成为我们工作.生活中的重要效率工具,乃至是伙伴,特别是为企业带来最原始最直观的"降本增效"落地实现. 作为开发者,你是否有想过基于语音技术打造 ...

  6. 最佳实践 | 基于腾讯云MRCP-Server打造简单智能外呼系统

    一.智能外呼架构简介 智能外呼在国内已发展多年,整体的技术早已非常成熟.那么一个简单的智能外呼系统应该包含哪些东西呢? 运营商:运营商的线路资源是外呼系统的基础,国内就是移动.联通.电信,也有一些集成 ...

  7. 最佳实践 | 基于腾讯云ES如何跨地域容灾?跨集群复制为您解忧!

    作者:吴容,腾讯云大数据Elasticsearch高级开发工程师 腾讯云大数据ES目前已经提供了多可用区部署,即支持同地域跨机房的高可用容灾方案,满足了绝大多数客户的需求.但是依然会有部分客户希望进一 ...

  8. 拍立淘-图像搜索与识别

    云栖TechDay40期,阿里巴巴iDST视觉技术总监启磐来给大家分享图像搜索和识别.本文主要从iDST和拍立淘业务开始谈起,接着分析了拍立淘技术框架,着重分析了拍立淘核心技术,最后展示了呈现效果和云 ...

  9. 腾讯云AI应用产品总监王磊:AI 在传统产业的最佳实践

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 背景:5月23-24日,以"焕启"为主题的腾讯"云+未来"峰会在广州召开,广东省各级政府机构领导.海 ...

最新文章

  1. java web dao_JavaWeb项目,DAO应该怎么写?
  2. python嵌套循环跳出_如何跳出嵌套的while循环
  3. Robot Cleaner I
  4. 抖音上非常火的旋转图快速部署
  5. Oracle 获取月初和月末
  6. java类和对象数组传参_java对象,数组作为参数传递给
  7. mats检测工具 400版_川崎新款忍者400新配色发布
  8. ES6/ES2015核心内容-转载
  9. DeleteDC、ReleaseDC、DeleteObject - [Daliy APIs]
  10. 5、烃源岩相关文献知识总结
  11. JS将阿拉伯数字翻译成中文的大写数字、JS将数字转换为大写金额(整理)
  12. conductor restart和rerun机制
  13. office2021官方正版镜像
  14. Android获取手机信息大全
  15. python 储蓄计划_储蓄--投资恒式为什么不意味着计划的储蓄恒等于计划的投资?...
  16. 用javaweb连接数据库用javabean、severlet实现增删改查
  17. 在深圳南山科技园的两年
  18. 第二届2011年国信蓝点杯软件设计大赛预赛的试题5
  19. word第几页,共几页
  20. 基于SpringBoot+VUE的服装销售商城管理系统

热门文章

  1. 深入浅出Centos7-ssh服务教程
  2. DD-WRT v24-sp2的WDS中继设置
  3. 解决 Office 2007/2010/2013 安装错误:1402
  4. 如何定时刷新一个View的内容呢? 酷课堂iOS交流群问答(201901期)
  5. LeetCode 264. 丑数 II--动态规划
  6. IDEA中MAVEN项目如何打包JAR包
  7. week 4 hw TT的神秘礼物 二分答案
  8. 【CodeForces 1255E1 --- Send Boxes to Alice [Easy Version]】
  9. Kali Linux 基于FreeFloat FTP Server编写漏洞渗透模块(下)
  10. 【java简单小项目】勇者斗魔王小游戏