广告图片过滤

为一个信息流产品作数据抓取,其中数据清洗时必不可少的。其中有一个步骤就是清洗掉其中与内容无关的广告。文本通过语料库积累和NLP相关技术进行过滤,有些文字广告不过滤对产品影响也不大。有点儿麻烦的是其中的有些图片广告如果不过滤掉,在感官上会对产品造成很大的印象,为了解决这个问题,用了一些杂七杂八的方法,始终没有一个唯一的解决方案。最终采用多级判断进行组合check(漏斗式缩小范围),在这里简单记录一下。

主要处理步骤如下图:

第一步:检查是否为二维码

文章开始和末尾的二维码一般都是广告(可以说至今没有发现不是的),由于二维码是编码良好的图片,可以不依赖材料库就可以判断,所以第一步先判断图片是否为二维码。

二维码判断Demo代码如下:

# coding:utf-8

import sys
from PIL import Image
import zbarlight

def is_qr_code(img):
    try:
        scan_result = zbarlight.scan_codes("qrcode", img)
    except Exception:
        return False
    else:
        #  打印QRCODE信息
        return True if scan_result else False

if __name__ == "__main__":
    img_name = sys.argv[1]
    ig = Image.open(img_name)
    print is_qr_code(ig)

若怕二维码中有重要信息,可以将从二维码图片中识别的文本信息做进一步的NLP处理,从而决定是否判定为广告

第二步:检查来源URL

有些广告图片都来同一个URL,比如某些自媒体/资讯平台会在每篇文章下面带有相同的广告图片,有的不是同一家产品的,但是采用了同一个广告平台都会出现这种情况。具体实现就是文本比对,代码就不用说了。

第三步:检查图片Hash-MD5(绝对指纹)

某些广告图片完全相同,但却来自不同的URL(比如,某些网站静态资源URI变更),用第二步的URL比对就不行了。在本步骤中采用图片内容的完全比对进行广告图片识别。若采用像素点比对那效率就太低了,所以采用MD5哈希值比对。MD5一般用于校验文件是否损坏、被修改,在这一步正好合适。

获取图片MD5哈希值的简单Demo代码:
Demo代码:

# coding:utf-8

import sys
from hashlib import md5

if __name__ == "__main__":
    img_name = sys.argv[1]
    img_body = open(img_name).read()
    fingerprint = md5(img_body).hexdigest()
    print fingerprint

第四步:检测图片感知哈希

参考:https://realpython.com/blog/python/fingerprinting-images-for-near-duplicate-detection/

在第三步中采用的MD5哈希比对对于内容完全相同的广告图片是适用的,但是一旦两张图片稍有差异,MD5就完全不同了,也就造成第三步的检测失效。所以在这里采用感知哈希进行相似图片的匹配(和广告图片相似的也是广告图片)。感知哈希是一类哈希算法。这里实验两种
DHash——均值感知哈希,
pHash——余弦变换感知哈希
均值哈希Demo代码:

# coding:utf-8

import sys
from PIL import Image


def dhash(image, hash_size=8):
    image = image.convert('L').resize(
        (hash_size + 1, hash_size),
        Image.ANTIALIAS,
    )

    difference = []
    for row in xrange(hash_size):
        for col in xrange(hash_size):
            pixel_left = image.getpixel((col, row))
            pixel_right = image.getpixel((col + 1, row))
            difference.append(pixel_left > pixel_right)

    decimal_value = 0
    hex_string = []
    for index, value in enumerate(difference):
        if value:
            decimal_value += 2 ** (index % 8)
        if (index % 8) == 7:
            hex_string.append(hex(decimal_value)[2:].rjust(2, '0'))
            decimal_value = 0

    return ''.join(hex_string)


if __name__ == "__main__":
    img_name = sys.argv[1]
    img = Image.open(img_name)
    print dhash(img)

第五步:人为定义特征

还可以通过其他人为定义特征进行过滤,以下特征可以考虑:

  • 色彩分布
  • 整体轮廓
  • ......

结束

本文只介绍了整个流程的实现demo。当然,在真正的业务项目中还牵涉到其他的组件。其中主要的时广告图片url、md5、指纹的存储和比对,就不介绍了,这和其他服务中的数据库的检索没什么区别,就是根据实际数据量进行设计&调整持久化、索引、缓存、备份、排序等相关策略。


后记:很早之前写的,写的不好,一直躺在草稿箱。现在发布出来,虽然已经不在进行这项工作了,还是希望有朋友提出改进的建议,谢谢!

posted @ 2018-04-06 16:35  Tacey Wong  阅读(2887)  评论(0编辑  收藏  举报