给出一串尺寸相同的商品鞋图片,将它们鞋头的朝向判断出来。例如:
先展示一下最后的效果:
思路:
其实找到规律非常简单。
- 我们首先得统一一下尺寸 1000 宽度,不然的话之后像素位置判断很难统一,这里可以使用批量的图片工具转一下就行(不要问为什么8张图也要转,我们模拟的是上千张图)。
- 接下来,我们需要开始找规律,再说之前,先来一张图:我们先分为两大区域,A区和B区,撇去logo不看,鞋子都有一个规律:右边低,左边高。我们就从这个地方切入。
nodejs分析图片像素:
初始化一个项目,然后安装下我们的依赖:npm i get-pixels --save
。这个包用于读取图的像素信息。 我们先展示下初始代码:
var getPixels = require("get-pixels");var fs = require("fs");
var path = require("path");
getPixels(img, function (err, pixels) {
if (err) {
return false
}else{
console.log(pixels)
}我是08年出道的高级前端老鸟,有问题或者交流经验可以进我的扣扣裙 519293536 我都会尽力帮大家哦
})
我们拿到了像素信息,我这里用了一张50-50像素的图片作为演示,图片太大不利于我们分析。发现它跑出来了这么多像素信息:
shap里面是我们的图片宽高等信息,data里面是像素的详细信息,但是它分的不够明确,50-50的图片,拆分出来了10000个像素信息,我们需要转化成像素,4个一个rgba,变成50-50的像素点,类似于这样的结构: [[rgb],[rgb],[rgb],[rgb]] 于是这块是我们接下来要去做的:
var arr = []; //对像素进行收集,三个一组rgbvar arrtemp = []; //临时的数组,用于储存拿到的临时三个rgb
pixels.data.forEach((item, index) => {
if (index % 4 === 0) {
arr.push(arrtemp)
arrtemp = [] //对像素储存空间重置
} else {
arrtemp.push(item)
}
});
复制代码
最后我们得到的 arr 就是我们需要的啦!这里变量的命名,我展示的比较随意,根据大家自己业务需求去命名,好的命名可维护性很重要哦。
接下来我们还需要去判断,第一个像素出现的位置。通过ps来吸一下颜色看看。
- 底色的颜色
- 物体的颜色
很明显,rgb数值越小,越可能出现我们需要的物体,那么这里就可以来做一个判断了。我这里设置的阈值是低于200,我就认为是物体,你们也可以根据自己需要来,我的代码只是大概粗略的,大家可以根据自己能力去优化:
var width = pixels.shape[0]; //收集图片宽度var arr = []; //对像素进行收集,三个一组rgb
var arrtemp = []; //临时的数组,用于储存拿到的临时三个rgb
var flag = true; //是否需要判断第一个目标像素点位置
var okIndex = 0; //目标像素出现的位置
var indexindex = 0; //记录循环中目标像素点的计数累加
pixels.data.forEach((item, index) => {
if (index % 4 === 0) {
arr.push(arrtemp)
indexindex++;
if (flag) {
if ((((arrtemp.filter((item2) => item2 < 200)).length) > 1)) { //像素值如果大于200 就是目标像素
okIndex = indexindex
flag = !flag
}
}
arrtemp = [] //对像素储存空间重置
} else {
arrtemp.push(item)
}
});
arr.shift()
console.log('最高像素出现在:', (okIndex / width).toFixed(2).toString().split('.')[1], '%位置上')
复制代码
做到这里之后,差不多鞋子的判断也都出来了
if ((okIndex / width).toFixed(2).toString().split('.')[1] < 50) { //只要超过画布一半 就认为是console.log('鞋头朝右')
res('鞋头朝右')
} else {
console.log('鞋头朝左')
res('鞋头朝左')
}
复制代码
但是这样会有一个问题,可以看到有些图片是带有左上角logo的,这种怎么解决呢? 也简单,我们设置一下行数,一张图片多少行像素之前,我们就先不判断它,到了后面几行,才开始判断。
const noCheckLine = 160; //需要忽略的行,例如顶上有Adidas logo打标干扰判断像素位置if ((((arrtemp.filter((item2) => item2 < 200)).length) > 1) && indexindex / width > noCheckLine) //像素值如果大于200 就是目标像素
复制代码
根据这样的判断,我们就可以从指定的行数才开始去找自己要的那个像素点了。
至此,我们如果需要批量的话,可以发现,这个东西其实是回调函数,不太好批量操作,我们封装成promise,加上async函数,完美~
var getPixels = require("get-pixels");var fs = require("fs");
var path = require("path");
(async () => {
......
})()
function getInformation(img) {
return new Promise((res, rej) => {
getPixels(img, function (err, pixels) {
if (err) {
rej('图片拉取失败!')
}
......
if ((okIndex / width).toFixed(2).toString().split('.')[1] < 50) { //只要超过画布一半 就认为是
res('鞋头朝右')
} else {
res('鞋头朝左')
}
})
})
}
复制代码
再展示一下最后的效果:
留下的问题:
拖鞋,凉鞋以及侧面的该怎么去判断呢?这里的方法并不适用于这些,但是并不代表着没有办法。
拖鞋类,我们可以反过来判断,那么怎么判断是不是拖鞋呢?像素信息密度就可以,指定一个阈值。 凉鞋类也可以根据具体的产品样本去找出规律。
- 问:这种准确率又达不到百分百,那还是不靠谱呀!
- 答:问题一般能解决掉95%,剩下来的5%就是调整参数了。如果需要更好的解决方案,可以尝试人工智能,但我想,那么大批量的素材需要训练出来,也许等训练完,肉眼都看完了....并且模型的训练,也要考虑到众多的样本特征。记住我:我是08年出道的高级前端老鸟,有问题或者交流经验可以进我的扣扣裙 519293536 我都会尽力帮大家哦
本文的文字及图片来源于网络加上自己的想法,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理