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

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

以下直接贴出代码(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. C4D中python初探

    use_name = input('请输入账号') password = input('请输入密码') if use_name == 'alex' and password == 'alex3714' ...

  2. [MtOI2019]幽灵乐团

    题目 一个很暴力的辣鸡做法 考虑到两个数的\(\gcd\)是所有质数次幂取\(\min\),两个数的\(\rm lcm\)是所有质数次幂取\(\max\),于是最后的答案一定是\(\prod p_i^ ...

  3. 初探.Net Core API 网关Ocelot(一)

    一.介绍 Ocelot 是基于.NetCore实现的开源的API网关,支持IdentityServer认证.Ocelot具有路由.请求聚合.服务发现.认证.鉴权.限流熔断等功能,并内置了负载均衡器与S ...

  4. 次梯度(Subgradient)

    参考链接:https://closure11.com/subgradient/

  5. java异常继承何类,运行时异常与一般异常的区别

    一.基本概念 Throwable是所有异常的根,java.lang.ThrowableError是错误,java.lang.ErrorException是异常,java.lang.Exception ...

  6. 3、docker 容器管理

    Docker容器相对于OpenStack的云主机实例,虽然他们本质上不同.我们需要基于镜像来创建容器.容器是独立运行的一个或一组应用,以及它们的运行环境.对应的,虚拟机可以理解为模拟运行的一整套操作系 ...

  7. The linux command 之进程

    ******************查看进程********************* 一.使用ps命令 [me@linuxbox ~]$ ps PID TTY TIME CMD pts/ :: ba ...

  8. 校园商铺-2项目设计和框架搭建-5配置maven

    /src/main/java 存放业务的Java代码 /src/main/resources 存储项目所用到的资源文件,如各种Spring,batis,日志的配置文件 /src/test/java 单 ...

  9. 配置文件一web.xml

    前言 web.xml中标签的加载顺序:<context-param> > <listener> (spring的相关工作) > filter >servlet ...

  10. 数论+线性dp——cf1174A

    直接推公式没有推出来 看了题解才会做.. 首先能够确定前面几个数的gcd一定是2^j * 3^k, 其中k<=1 那么可以用dp[i][j][k]来表示到第i位的gcd是2^j*3^k f(j, ...