作者:yikfunwu 腾讯PCG开发工程师
|导语 泰山智能设计平台已经为业务每天生成素材1w+。在批量制图的过程中,我们发现有时服务器会制作生成一些『异常』的图片…怎么能在图片投放前检测出这种图像,提高图片的可用度呢?
我们从图像数据,图像渲染和图像内容本身,从里到外三个角度来考虑图像可用性的问题。
01
图像数据
这里说的图像数据也就是图片的文件数据。
如果图片在渲染写入过程中意外中断了,会直接导致生成的图片不完整,丢失后面的内容。如下图所示:
这种情况因为其文件数据结构不完整,所以可以用正常图片格式的文件头尾来判断图片信息是否完整。
以常用的JPEG图片格式为例,从维基百科的JPEG文件格式中可以看到,正常的JPEG文件头会以字节 0xFF, 0xD8 开头,以 0xFF, 0xD9 结尾。因为大多数情况是图片尾部的信息不完整,所以直接用文件尾的信息来判断即可。
let response = await axios.get(imageUrl, { responseType: 'arraybuffer' });
let endByte = response.data.slice(response.data.length - 2);
let correctEnd = new Buffer([0xff, 0xd9]);
if (!correctEnd.equals(endByte)) {
console.log("image data error")
}
通过以上方式可以首先排查出因为图片文件本身的数据问题导致的图像不可用情况。
02
图像渲染
图片渲染错误一般是因为网络波动问题,服务器拉取对应的元素图片失败,导致渲染出来的图片里有黑屏的情况。如下图所示:
这种情况可以通过图片中黑色像素值的占比来判断图片是否可用。
但黑色像素不能简单地用纯黑的色值(r=0,g=0,b=0)来判断,因为图片里的一些修饰元素的效果(投影,渐变等)会使原本黑色的区域发灰。上右图底部文字的背景实际上就不是纯黑的。所以我们需要把判断颜色的阈值放大些,如果r,g,b值都小于30,则判定为『黑色像素』。『黑色像素』超过图片总像素90%,则判断为错误图片不可用。
const Canvas = require("canvas")
let canvas = new Canvas(imgWidth, imgHeight)
let ctx = canvas.getContext('2d');
let Image = Canvas.Image;
let img = new Image;
img.src = buffer;
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
let imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
let pixelNum = imageData.data.length / 4;
let blackNum = 0;
for (let i = 0; i < imageData.data.length; i += 4) {
let r = imageData.data[i];
let g = imageData.data[i + 1];
let b = imageData.data[i + 2];
if (r < 30 && g < 30 && b < 30) {
blackNum++
}
}
if (blackNum / pixelNum * 100 >= 90){
console.log("image render error")
}
通过上面的方式就可以排查出因为网络问题导致元素内容拉取失败渲染出黑屏的问题了。
03
图像内容
图像内容涉及的范围有很多,这里我们以最基础的一个维度为例,来判断图片是否可用:图片的重点区域是否被遮挡,有没有正常显示。如下图所示:
对于有人物的素材里,人脸是最重要的信息。我们会识别出原始素材的人脸区域,然后通过算法把素材调整在合适的位置,保证人脸不会被裁切,重点得到正常的显示。
除此之外,我们的AI识别能力还针对动漫/游戏场景的人物做了训练优化,保证这种卡通类的人脸也得到准确的识别。在一些模板场景里,我们还会根据素材的比例,朝向和贴边的信息,自动缩放和翻转素材来让整个版式更协调,提高图片的可用度。
通过上面对素材重点信息的识别与处理,我们可以有效突出图像的重点内容,提高图片的可用度。
04
总结
以上,我们分别从图像数据,图像渲染,图像内容,从内到外三个角度来检测和提升图像的可用度。
近期热文
让我知道你在看