拍立淘抠图体验优化总结

简介: 本文将介绍拍立淘结果页从上线至今出现的体验问题及解决方案

前言

拍立淘结果页从上线至今,经历了许多年的迭代,始终保留了一个抠图的功能——用户可以在图片上自主选择要搜索的图片区域

image.png

功能经过这么多年使用,由于当初的实现没有那么精细,导致一直存在一些体验上的问题,用户重点反馈的内容包含以下几个部分:

  1. 抠图不易操作
  2. 找不到抠图框
  3. 小物件搜索不出来
  4. ....


基于以上这些问题,我们进行了一一解决,下面进入正题。


交互体验

 找不到框


用户在进入结果页后,会在背景处显示一整张原图,由于底部存在结果面板,导致图片显示区域被压缩,所以会有一部分图片被隐藏,对于不了解功能的用户来说,不知道图片是可以滑动的,假如主体框刚好就在隐藏的图片区域里,用户就没法框选主体了。

image.png

 抠图不易操作


原先的抠图组件存在一些bug

  • 触摸冲突

image.png

image.png

image.png

抠图组件包含以下几种基础操作

  1. 边框四个角调整
  2. 边框四个边调整
  3. 边框整体位置调整
  4. 主体圆点选中


原先的抠图组件对于触摸的逻辑缺少封装设计,所有逻辑都糅合在一个类中,代码不易维护。重构后的组件对于抠图操作进行了抽象,基于手指的动作,抽象了以下接口

/**
 * 前置判断
 */
fun judge(fingerArray: SparseArray<FingerPos>, selectedObjectRegion: RegionPart, totalObjects: List<RegionPart>, selfDefinedObject: RegionPart): Boolean
/**
 * 手指松开
 */
fun onTouchRelease(selectedObjectRegion: RegionPart, totalObjects: List<RegionPart>, selfDefinedObject: RegionPart)
/**
 * move 回调
 */
fun onTouchEvent(fingerArray: SparseArray<FingerPos>, selectedObjectRegion: RegionPart, totalObjects: List<RegionPart>, selfDefinedObject: RegionPart): Boolean

基于组件提供的操作,进行了以下封装

image.png


后续若有新的操作,继承拓展即可

对于触摸操作,我们定义了以下优先级,优先级从高到低排列

  1. 主体点击
  2. 图片缩放
  3. 四角调整
  4. 四边调整
  5. 框体位置调整
  6. 图片移动

触摸流程如下

640.png

图片缩放

由于图片整体缩放到了结果面板上方,如果用户想要搜一些特别小的物件,例如模特手上的手表,那么必然不好操作,因此我们增加了图片缩放的功能,图片缩放功能完全还原iOS系统相册的实现。

image.png

下面介绍一下缩放的实现。



观察 iOS系统相册的缩放能力,可以发现,当双指缩放图片时,图片会基于双指中间那一点进行缩放,保证双指中间的内容是不变的。

image.png

并且当手指距离不变,围绕一个点旋转时,手指中间的那个像素是始终不变的。


  • 旋转

image.png

image.png

基于以上观察,我们可以得出基本的实现方案

  1. 双指按下时,计算出当前双指中间的像素点在图片上的绝对坐标
  2. 双指移动时,基于手指移动的距离,放大或者缩小图片
  3. 双指移动时,保证按下时的中间像素点始终保持在手指中间
 override fun onTouchEvent(fingerArray: SparseArray<FingerPos>, selectedObjectRegion: RegionPart, totalObjects: List<RegionPart>,selfDefinedObject : RegionPart): Boolean {
        targetView ?: return false
        if (fingerArray.size() < 2) {
            scale = -1f
            return true
        }
        val pos1 = fingerArray[0] ?: return true
        val pos2 = fingerArray[1] ?: return true
        if (scale < 0) {
            //刚触发双指缩放,记录当前scale 值
            scale = targetView!!.getImageView().scaleX
            ...
            //记录手指中间的像素坐标
            centerPosition = getCenterPosition(pos1, pos2)
        }
        //计算当前双指距离
        val currentDistance = sqrt((sqr(pos1.currX - pos2.currX) + sqr(pos1.currY - pos2.currY)).toDouble()).toFloat()
        //计算上一次触摸时的双指距离
        val lastDistance = sqrt((sqr(pos1.lastX - pos2.lastX) + sqr(pos1.lastY - pos2.lastY)).toDouble()).toFloat()
        //计算第一次进入双指缩放时的手指距离
        val startDistance = sqrt((sqr(pos1.startX - pos2.startX) + sqr(pos1.startY - pos2.startY)).toDouble()).toFloat()
        val delta = (currentDistance - lastDistance) / startDistance
        zoomScale += delta
        zoomScale = maxDelta.coerceAtMost(minDelta.coerceAtLeast(zoomScale))
        val currScale = scale * zoomScale
        targetView!!.setImageScale(currScale)
        //计算缩放后的手指中间像素坐标
        val currPos = getCenterPosition(pos1, pos2)
        //根据坐标和 scale,移动图片,保证图片在正确的位置
        moveImage((currPos[0] - centerPosition!![0]) * currScale, (currPos[1] - centerPosition!![1]) * currScale, false)
        return true
    }

抠图流程

 流程梳理


  • 结果页流程

image.png

可以看到,在发送请求时,会先缩放一次图片(长边最长640,短边最长320),然后服务端处理完成后,同时将图片保存到存储服务上,生成链接,连同内容数据打包回传给端上,然后端上交付给前端进行渲染。


  • 用户抠图流程

image.png

 现有问题


分析以上流程就会发现,客户端初始化请求时将图片进行了缩小,上传到服务端以后会得到一个图片链接,后续前端的所有请求都会基于这个链接。因此,如果用户想要搜索一个模特手上的手表,对于用户来说,手表看着挺大的,但是如果是缩放后的图,手表那一点大小,基本是不可识别的。

image.png

可以看到,此时搜索后的结果和图片内容是完全无关的。

 优化


我们对抠图后的流程做了调整,当用户想要搜索的图片区域做了调整后,端上将图片从原始图片(未缩放)中切割出来,重新走一遍图片上传流程,基于切割后的图进行商品召回,增大 query 图像的尺寸,提高准确度。

网络异常,图片无法展示
|

可以看到效果十分明显,优化后的搜索结果和商品相关度大幅度上涨。


总结

对于老代码,我们要勇于去优化重构,勿以点小而不为(手动滑稽~)目前整体改动已经跟随 10.15.0 版本上线,并且增加了 ab,相信数据上会有较大的提升~

相关文章
|
存储 缓存 Oracle
常识四堆外内存
常识系列,作为一名互联网门外汉的科普系列 堆外内存除了在像netty开源框架中,在平常项目中使用的比较少,在现前的项目中,QPS要求高的系统中,堆外内存作为其中一级缓存是相当有成效的。所以来学习一下,文中主要涉及到这三分部内容 1. 堆外内存是什么?与堆内内存的区别 2. 怎么分配,与GC的影响 3. 开源框架使用 这篇文章写到最后,发现还只是回答了开源框架OHC的Why not use ByteBuffer.allocateDirect()?
1789 1
常识四堆外内存
|
机器学习/深度学习 人工智能 缓存
每个人都可以成为虚拟主播,一键创建属于你的虚拟形象,RAIN 为你实时生成逼真动画角色
RAIN 是一款创新的实时动画生成工具,支持在消费级硬件上实现无限视频流的实时动画化,适用于直播、虚拟角色生成等场景。
790 25
每个人都可以成为虚拟主播,一键创建属于你的虚拟形象,RAIN 为你实时生成逼真动画角色
|
IDE 开发工具 Python
PyCharm IDEA 安装【Chinese(Simplified)Language Pack/中文语言包】插件汉化出错
安装【Chinese(Simplified)Language Pack/中文语言包】插件时报【Plugin Installation】错误
9120 1
PyCharm IDEA 安装【Chinese(Simplified)Language Pack/中文语言包】插件汉化出错
|
机器学习/深度学习 人工智能 大数据
基于深度学习的图像识别技术最新进展####
近年来,深度学习在图像识别领域取得了显著突破,本文综述了该领域的最新研究进展,特别关注卷积神经网络(CNN)的优化与创新、数据集扩充与增强策略、以及模型压缩与加速技术。通过对比分析不同网络结构和训练技巧,揭示了提升图像识别精度与效率的关键因素。此外,探讨了小样本学习、迁移学习在实际应用中的挑战与解决方案,为未来研究方向提供了新的视角和思路。 ####
1320 8
|
机器学习/深度学习 人工智能 算法
神经形态计算:模拟大脑的计算方式
【10月更文挑战第11天】神经形态计算作为一种新兴的计算范式,正以其独特的优势和广阔的应用前景吸引着越来越多的关注。通过模拟大脑的计算方式,神经形态计算不仅能够提高计算速度和能效,还能在处理复杂任务时展现出更高的智能水平。我们有理由相信,在未来的发展中,神经形态计算将为我们带来更多的惊喜和突破,引领我们进入一个全新的计算时代。
|
10月前
|
分布式计算 Java 大数据
Java 大视界 —— 基于 Java 的大数据分布式计算在气象数据处理与天气预报中的应用进展(176)
本文围绕基于 Java 的大数据分布式计算在气象数据处理与天气预报中的应用展开,剖析行业现状与挑战,阐释技术原理,介绍其在数据处理及天气预报中的具体应用,并结合实际案例展示实施效果。
|
Web App开发 监控 前端开发
React音频播放控制组件开发深度解析
本文介绍了构建React音频控制组件时遇到的关键问题及优化方案。主要包括: 1. **状态同步难题**:解决播放按钮与音频状态不同步的问题,通过双向绑定机制确保一致。 2. **跨浏览器兼容性**:处理Safari和Chrome预加载策略差异,确保`duration`属性正确获取。 3. **进度控制优化**:避免使用`setInterval`,采用`requestAnimationFrame`提升性能;优化拖拽交互,防止音频卡顿。 4. **音量控制进阶**:实现渐变音量调节和静音状态同步。
552 15
|
前端开发 容器
CSS 居中技术完全指南:从基础到高级应用
本文详细介绍了 CSS 中常用的居中方法,涵盖水平居中、垂直居中及同时实现两者的方法。
1371 12
|
存储 监控 物联网
计算机网络的应用
计算机网络已深入现代生活的多个方面,包括通信与交流(电子邮件、即时通讯、社交媒体)、媒体与娱乐(在线媒体、在线游戏)、商务与经济(电子商务、远程办公)、教育与学习(在线教育平台)、物联网与智能家居、远程服务(远程医疗、智能交通系统)及数据存储与处理(云计算、数据共享与分析)。这些应用极大地方便了人们的生活,促进了社会的发展。
977 2
计算机网络的应用
|
人工智能 自然语言处理 计算机视觉
AI大模型开启智能化新时代
12月19日下午,复旦大学计算机科学技术学院第十二期“步青讲坛”在江湾校区二号交叉学科楼E1006报告厅举行。本期讲坛特别邀请了阿里巴巴集团副总裁、IEEE Fellow叶杰平教授做题为《AI大模型开启智能化新时代》的精彩技术报告。
499 4

热门文章

最新文章