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

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

以下直接贴出代码(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. 协方差及matlib绘制

    转自http://www.cnblogs.com/chaosimple/p/3182157.html 一.统计学的基本概念 统计学里最基本的概念就是样本的均值.方差.标准差.首先,我们给定一个含有n个 ...

  2. SPRING+JPA+Hibernate配置方法

    1.applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...

  3. C++ vector操作--往列表中添加或更新内容

    有个列表,往里面添加内容,如果对象已存在,只更新其属性,否则添加新一项. #include <iostream> #include <string> #include < ...

  4. 9_山寨系统调用 SystemCallEntry

    思想: 再次在 GDT 中偷内存 搭建 系统调用需要的 逻辑框架与功能实现: 基本分解妄想: 构建系统调用的代码: 拷贝到 偷取的内存中: idt 向量 序号21位置: 8003ee00`0008f1 ...

  5. 无法解析的外部符号 jpeg_std_error

    1>dlib.lib(png_loader.obj) : error LNK2001: 无法解析的外部符号 png_set_sig_bytes 1>dlib.lib(png_loader. ...

  6. js实现获取选中checkbox的值

    var bookVersionId = []; var examVirtualSetResultId; $.each($('input[type=checkbox]:checked'),functio ...

  7. CSS——垂直居中

    vertical-align 垂直对齐 以前我们讲过让带有宽度的块级元素居中对齐,是margin: 0 auto; 以前我们还讲过让文字居中对齐,是 text-align: center; 但是我们从 ...

  8. thinkphp ASSIGN标签

    ASSIGN标签用于在模板文件中赋值变量,用法如下: 直线电机厂家 <assign name="var" value="123" /> 在运行模板的 ...

  9. SpringCloud及其五大常用组件之Eureka和Zuul

    1.springcloud简介 SpringCloud是Spring旗下的项目之一,它是微服务架构的一种实现方式. 官网地址:http://projects.spring.io/spring-clou ...

  10. P1977 出租车拼车

    P1977 出租车拼车 题目背景 话说小 x 有一次去参加比赛,虽然学校离比赛地点不太远,但小 x 还是想坐 出租车去.大学城的出租车总是比较另类,有“拼车”一说,也就是说,你一个人 坐车去,还是一堆 ...