作者感言:数学不好,遇到算法问题分分钟狗带,毫无转寰的余地-_-|||

最近心血来潮,看了相似图片的搜索,最最最初级的方法即提取汉明码,之后匹配汉明距离。当然,在数以亿计的汉明码中,要筛出需要的图片,计算量太大了,满足不了生产要求。作为数学小白,此时完全没折了。这时不小心看到“降维”一说,可以把降维后的哈希码存入数据库,加之分类的约束,基本满足小白初尝电商相似图片搜索的要求了:)

以下直接贴出代码(2017-8-17傍晚对降维做了调整):

class DFingerPrint
{
private $hImg=null;
private $hTargetImg=null;
private $arrResult=array(); private $fullBinData=''; const PRINT_WIDTH=8;
const PRINT_HEIGHT=8; public const DESC_DM_2=2;
public const DESC_DM_4=4;
public const DESC_DM_8=8; public function __construct($imgPath)
{
if(file_exists($imgPath))
{
$ext=$this->GetExt($imgPath);
$create_fun='';
switch($ext)
{
case 'jpg':
case 'jpeg':
$create_fun='imagecreatefromjpeg';
break;
case 'gif':
$create_fun='imagecreatefromgif';
break;
case 'png':
$create_fun='imagecreatefrompng';
break;
case 'bmp':
$create_fun='imagecreatefrombmp';
break;
default:
$create_fun='imagecreatefromgd2';
break;
} $this->hImg=$create_fun($imgPath);
if($this->hImg===false) $this->hImg=null;
} if($this->hImg)
{
$this->hTargetImg=imagecreatetruecolor(self::PRINT_HEIGHT,self::PRINT_HEIGHT);
}
} public function CalPrint()
{
if(!$this->hImg) return false;
if(!$this->SizeCompress()) return false;
if(!$this->ToGray()) return false;
if(!($binData=$this->Binaryzation())) return false; $this->fullBinData=$binData;
//$hexData=base_convert($binData,2,16); //这一句转出来问题,尾数错误,原因未知
$hexData=$this->Bin2Hex($binData); return array(
'bin'=>$binData,
'hex'=>$hexData
);
} public function DecendDimension($dm=8) //可指定降维参数,参数越大,精度缺失越多
{
if(!$this->fullBinData) return false;
if(!in_array($dm,array(self::DESC_DM_2,self::DESC_DM_4,self::DESC_DM_8))) return false; $len=strlen($this->fullBinData);
$newBinData='';
for($i=0,$iTmp=0;$i<$len;$i++)
{
$iTmp+=$this->fullBinData{$i}=='1'?1:-1; if($dm-($i%$dm)==1)
{
$newBinData.=$iTmp>0?1:0;
$iTmp=0;
}
} $hexData=$this->Bin2Hex($newBinData); return array(
'bin'=>$newBinData,
'hex'=>$hexData
);
} /*
public function DecendDimension($dm=1) //二值降维
{
if(!$this->arrResult) return false; $binData='';
for($x=0;$x<self::PRINT_WIDTH;$x++)
{
$rtl=0;
for($y=0;$y<self::PRINT_HEIGHT;$y++)
{
$rtl+=$this->arrResult[$x][$y]==1?1:-1;
}
$binData.=$rtl>0?'1':'0';
} $hexData=$this->Bin2Hex($binData); return array(
'bin'=>$binData,
'hex'=>$hexData
);
}
*/ private function SizeCompress() //尺寸压缩
{
if(!$this->hImg) return false; imagecopyresized($this->hTargetImg,$this->hImg,0,0,0,0,8,8,imagesx($this->hImg),imagesy($this->hImg));
return true;
} private function ToGray() //灰度化
{
for($x=0;$x<self::PRINT_WIDTH;$x++)
{
for($y=0;$y<self::PRINT_HEIGHT;$y++)
{
$color=imagecolorat($this->hTargetImg,$x,$y);
$_red = ($color >> 16) & 0xff;
$_green = ($color >> 8) & 0xff;
$_blue = ($color) & 0xff; $newColor= intval(0.3 * $_red + 0.59 * $_green + 0.11 * $_blue); $this->arrResult[$x][$y]=$newColor;
}
}
return true;
} private function Binaryzation() //二值化
{
if(!$this->arrResult) return false;
if(sizeof($this->arrResult)!=self::PRINT_WIDTH) return false; $totalVal=0;
$avgVal=0;
for($x=0;$x<self::PRINT_WIDTH;$x++)
{
for($y=0;$y<self::PRINT_HEIGHT;$y++)
{
$totalVal+=$this->arrResult[$x][$y];
}
}
$avgVal=$totalVal/(self::PRINT_HEIGHT*self::PRINT_HEIGHT); //开始二值化
$binData='';
for($x=0;$x<self::PRINT_WIDTH;$x++)
{
for($y=0;$y<self::PRINT_HEIGHT;$y++)
{
if($this->arrResult[$x][$y]>=$avgVal) $this->arrResult[$x][$y]=1;
else $this->arrResult[$x][$y]=0; //imagesetpixel($this->hTargetImg,$x,$y,$this->arrResult[$x][$y]==1?0xffffff:0x00);
$binData.=strval($this->arrResult[$x][$y]);
}
} return $binData;
} public function __destruct()
{
if($this->hImg)
{
imagedestroy($this->hImg);
$this->hImg=null;
}
if($this->hTargetImg)
{
imagedestroy($this->hTargetImg);
$this->hTargetImg=null;
} } private function GetExt($path)
{
$arr=explode('.',$path);
return strtolower($arr[sizeof($arr)-1]);
} private function Bin2Hex($bin)
{
$hex='';
$i=1;
while($bin)
{
$tmp_bin=substr($bin,-4,4);
$hex=base_convert($tmp_bin,2,16).$hex; $bin=substr($bin,0,strlen($bin)-4);
}
return $hex;
}
}

调用

$oFingerPrint=new DFingerPrint('1.jpg');
$arrPrint=$oFingerPrint->CalPrint();
$arrDescendPrint=$oFingerPrint->DecendDimension(DFingerPrint::DESC_DM_8);

查看资料:

http://blog.csdn.net/lu597203933/article/details/45101859

http://blog.csdn.net/cshilin/article/details/52119682

附:从MYSQL中查出指定汉明距离的的SQL语句:

SELECT uid,img_path,full_print2,
BIT_COUNT(CONVERT(CONV(full_print2, 16, 10),UNSIGNED) ^ CONVERT(CONV('ffffe229f9ffffff', 16, 10),UNSIGNED) ) as hamming_distance
FROM mvm_img_fingerprint
HAVING hamming_distance < 5
ORDER BY hamming_distance ASC;

PHP实现图片的汉明码提取与降维的更多相关文章

  1. python画图库及函数,绘制图片从文件提取出来的数据集转化为int,不然作为坐标轴的时候因为是字符串而无法排序

    转化int:  

  2. 使用SAP Leonardo上的机器学习服务提取图片的特征向量

    要想提取图片的特征向量,首先得知道特征向量是什么. 我们假设这样一个服务场景,技师上门维修某设备,发现上面某零件损坏了,假设这位技师由于种种原因,没能根据自己的经验识别出这个零件的型号.此时技师掏出自 ...

  3. C# 提取Word文档中的图片

    C# 提取Word文档中的图片 图片和文字是word文档中两种最常见的对象,在微软word中,如果我们想要提取出一个文档内的图片,只需要右击图片选择另存为然后命名保存就可以了,今天这篇文章主要是实现使 ...

  4. R+OCR︱借助tesseract包实现图片文本提取功能

    2016年11月,Jeroen Ooms在CRAN发布了tesseract包,实现了R语言对简单图片的文本提取.分析功能. 利用开源OCR引擎进行图片处理,目前可以识别超过100种语言,R语言可以借助 ...

  5. 网页图片提取助手(支持背景图、选择dom范围)

    网页图片提取助手(支持背景图.选择dom范围) 网页图片下载工具.网页图片批量保存. 使用场景: 作为web前端开发首——学习小生的你我,仿学在线页面是常有的事,但是一些在线资源,比如图片,图片有im ...

  6. Java 提取Word中的文本和图片

    本文将介绍通过Java来提取或读取Word文档中文本和图片的方法.这里提取文本和图片包括同时提取文档正文当中以及页眉.页脚中的的文本和图片. 使用工具:Free Spire.Doc for Java ...

  7. Python opencv提取视频中的图片

    作者:R语言和Python学堂链接:https://www.jianshu.com/p/e3c04d4fb5f3 这个函数就是本文要介绍的video2frames()函数,功能就是从视频中提取图片,名 ...

  8. opencv中对图片的二值化操作并提取特定颜色区域

    一.最近因为所在的实习公司要求用opencv视觉库来写一个对图片识别并提取指定区域的程序.看了很多资料,只学会了皮毛,下面附上简单的代码.运行程序之前需要安装opencv库,官网地址为:https:/ ...

  9. SAP Leonardo图片处理相关的机器学习服务在SAP智能服务场景中的应用

    本文作为Jerry最近正在做的一个项目的工作思路的梳理. 我们假设这样一个服务场景,技师上门维修某设备,发现设备上某零件损坏了,假设这位技师由于种种原因,没能根据自己的经验识别出这个零件的型号.此时技 ...

随机推荐

  1. C++之程序流程_选择结构

    C/C++支持最基本的三种程序运行结构:==顺序结构.选择结构.循环结构== * 顺序结构:程序按顺序执行,不发生跳转* 选择结构:依据条件是否满足,有选择的执行相应功能* 循环结构:依据条件是否满足 ...

  2. 【学术篇】SDOI2009 最优图像

    又是一道辣鸡卡常数题…. luogu上有些题的时限还是有毒的… 最后也只能靠O2过掉了… 不过给我原题当时的2s我随便过给你看嘛, 哪怕评测姬慢50%都没关系的.. 贴一下codevs的截图… 你看最 ...

  3. event.target.tagName

    html中 event.target.tagName 中的tagName属性他返回的就是元素标签的大写名称 例如标签他的tagName就是EM 所以用大写 记住:在 HTML 中,tagName 属性 ...

  4. .Net 动态编译(c# 脚本)

    1 用.NET提供的类动态编译代码字符串,生成DLL存于内存中,加载到程序域 2 用反射的方式调用这个DLL 将要被编译和执行的代码读入并以字符串方式保存声明CSharpCodeProvider对象实 ...

  5. sudo: /etc/sudoers is world writable|给用户添加权限报错

    给用户添加权限时候出现:sudo: /etc/sudoers is world writable| sudo: /etc/sudoers is world writable解决方式: pkexec c ...

  6. [SNOI 2017] 炸弹

    题目描述: 给定炸弹和爆炸范围,求对于每个炸弹连锁爆炸的炸弹总和对\(1e9+7\)取膜 思路: 为啥都是线段树+TS+tarjan呢? 实在是搞不懂~~ 线性\(O(n)\)递推即可. #inclu ...

  7. Unity3D Input 键盘控制

    function Update (){ //Input.GetKey ("down") == Input.GetKey(KeyCode.DownArrow) if (Input.G ...

  8. linux安装PyCharm,PyCharm常用快捷键及调试模式,pycharm里面对文件夹或者文件进行重命名

    PyCharm常用快捷键及调试模式 2017年10月18日 23:13:43 菜鸟之神 阅读数:5835    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn ...

  9. c# 中xml序列化时相同节点存入不同类型值

    先上需要序列话的类定义: [System.Xml.Serialization.XmlIncludeAttribute(typeof(DescriptionType))] [System.CodeDom ...

  10. js实现前端动态筛选表格内容

    代码参考: http://www.sharejs.com/codes/javascript/4289 http://www.jb51.net/article/103420.htm https://ww ...