Gao Conghui

好好学习,天天向上

爬虫,视频处理


phash计算png图片指纹返回总为0

今天在用phash做线上封面图去重,之前自己开发机mac上有个用port install phash安装的phash,源码是phash.org中提供的c++版本的,没遇到啥问题。今天打算用docker包一下放服务器上跑,发现了个有趣的现象,所有的png图片计算出来的指纹都是0。

In [214]: lib = ctypes.CDLL(find_library('pHash'), use_errno=True)

In [215]: phash = ctypes.c_uint64()

In [216]: lib.ph_dct_imagehash("/tmp/new3.png", ctypes.pointer(phash))
Out[216]: 0

In [217]: phash
Out[217]: c_ulong(0L)

而后在mac上直接编译使用,结果同上,也是总为0。很有意思,一开始一直在检查自己的代码,直到简化成只剩几行了,还是有问题。一直没敢怀疑phash.org上已经放出来好几年的代码,毕竟那一套东西2013年之后就没变过了,应该没啥太大问题。

04.23.2013 pHash 0.9.6 released. Fix some compilation errors and warnings, as well as updates to the automake files to support building on Gentoo.

而后开始对源码进行修改,采用print大法来debug,才发现真的是phash写的有些问题。

CImg<float> img;
if (src.spectrum() == 3){
        img = src.RGBtoYCbCr().channel(0).get_convolve(meanfilter);
    } else if (src.spectrum() == 4){
	int width = img.width();
        int height = img.height();
        int depth = img.depth();
	img = src.crop(0,0,0,0,width-1,height-1,depth-1,2).RGBtoYCbCr().channel(0).get_convolve(meanfilter);
    } else {
	img = src.channel(0).get_convolve(meanfilter);
    }
img.resize(32,32);

这段代码来源于ph_dct_imagehash方法,就是算phash的核心方法,这边用Cimg对图像做了一些处理,src是输入的原始图片,img应该是处理完之后的,生成一个32*32的图片。src.spectrum()方法获取图片通道,png图片有RGBA四个通道,问题就出在这,这块应该是想获取图片的宽高信息,而后做截图处理。然而img还没初始化,返回的都只能是0,导致后边各种计算返回一片0,修改为src后即可。

else if (src.spectrum() == 4){
	int width = src.width();
        int height = src.height();
        int depth = src.depth();
	img = src.crop(0,0,0,0,width-1,height-1,depth-1,2).RGBtoYCbCr().channel(0).get_convolve(meanfilter);
    }

#####小记

说实话,这是我第一次对权威的代码(这应该算权威吧?)动手,只能说,代码总是人写的,总是会有bug的。

最近的文章

chrome抓包websocket frame为空

尝试抓websocket的包,遇上一个奇葩的问题,分享下。测试网站如下http://websocket.org/echo.htmlchrome抓websocket的包很简单 打开http://websocket.org/echo.html connect ,send,可以在前端看到输出 打开chrome开发者工具,可以看到已经有websocket的连接然而…啥都没有…很迷,看了许久,搜了很多地方,换了电脑,升级了最新版本,依旧啥都没有…终于,在StackOverflow 上找到了靠谱...…

websocket继续阅读
更早的文章

python实现redis三种cas操作

cas全称是compare and set,是一种典型的事务操作,本文会介绍三种redis实现cas事务的方法,并会解决下面的虚拟问题:维护一个值,如果这个值小于当前时间,则设置为当前时间;如果这个值大于当前时间,则设置为当前时间+30。简单的单线程环境下代码如下:# 初始化r = redis.Redis()if not r.exists("key_test"): r.set("key_test", 0)def inc(): count = int(r.get('key_tes...…

redis python继续阅读