PHP实现图片的汉明码提取与降维
作者感言:数学不好,遇到算法问题分分钟狗带,毫无转寰的余地-_-|||
最近心血来潮,看了相似图片的搜索,最最最初级的方法即提取汉明码,之后匹配汉明距离。当然,在数以亿计的汉明码中,要筛出需要的图片,计算量太大了,满足不了生产要求。作为数学小白,此时完全没折了。这时不小心看到“降维”一说,可以把降维后的哈希码存入数据库,加之分类的约束,基本满足小白初尝电商相似图片搜索的要求了:)
以下直接贴出代码(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实现图片的汉明码提取与降维的更多相关文章
- python画图库及函数,绘制图片从文件提取出来的数据集转化为int,不然作为坐标轴的时候因为是字符串而无法排序
转化int:
- 使用SAP Leonardo上的机器学习服务提取图片的特征向量
要想提取图片的特征向量,首先得知道特征向量是什么. 我们假设这样一个服务场景,技师上门维修某设备,发现上面某零件损坏了,假设这位技师由于种种原因,没能根据自己的经验识别出这个零件的型号.此时技师掏出自 ...
- C# 提取Word文档中的图片
C# 提取Word文档中的图片 图片和文字是word文档中两种最常见的对象,在微软word中,如果我们想要提取出一个文档内的图片,只需要右击图片选择另存为然后命名保存就可以了,今天这篇文章主要是实现使 ...
- R+OCR︱借助tesseract包实现图片文本提取功能
2016年11月,Jeroen Ooms在CRAN发布了tesseract包,实现了R语言对简单图片的文本提取.分析功能. 利用开源OCR引擎进行图片处理,目前可以识别超过100种语言,R语言可以借助 ...
- 网页图片提取助手(支持背景图、选择dom范围)
网页图片提取助手(支持背景图.选择dom范围) 网页图片下载工具.网页图片批量保存. 使用场景: 作为web前端开发首——学习小生的你我,仿学在线页面是常有的事,但是一些在线资源,比如图片,图片有im ...
- Java 提取Word中的文本和图片
本文将介绍通过Java来提取或读取Word文档中文本和图片的方法.这里提取文本和图片包括同时提取文档正文当中以及页眉.页脚中的的文本和图片. 使用工具:Free Spire.Doc for Java ...
- Python opencv提取视频中的图片
作者:R语言和Python学堂链接:https://www.jianshu.com/p/e3c04d4fb5f3 这个函数就是本文要介绍的video2frames()函数,功能就是从视频中提取图片,名 ...
- opencv中对图片的二值化操作并提取特定颜色区域
一.最近因为所在的实习公司要求用opencv视觉库来写一个对图片识别并提取指定区域的程序.看了很多资料,只学会了皮毛,下面附上简单的代码.运行程序之前需要安装opencv库,官网地址为:https:/ ...
- SAP Leonardo图片处理相关的机器学习服务在SAP智能服务场景中的应用
本文作为Jerry最近正在做的一个项目的工作思路的梳理. 我们假设这样一个服务场景,技师上门维修某设备,发现设备上某零件损坏了,假设这位技师由于种种原因,没能根据自己的经验识别出这个零件的型号.此时技 ...
随机推荐
- js面向对象编程:this究竟代表什么?第二篇
总觉得自己弄明确了js中this的含义.this总是指向调用方法的对象,作为方法调用,那么this就是指实例化的对象.但前几天自己写脚本却遇到了一个非常奇怪的问题. 代码例如以下: ...
- 错误Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FSDataInputStream排查思路
spark1(默认CDH自带版本)不存在这个问题,主要是升级了spark2(CDHparcel升级)版本安装后需要依赖到spark1的旧配置去读取hadoop集群的依赖包. 1./etc/spark2 ...
- Django form组件 与 cookie/session
目录 一.form组件 二.cookie.session 返回Django 组件 一.form组件 1.1 以注册功能为例 注册功能 1.渲染前端标签获取用户输入 --> 渲染标签 2.获取用户 ...
- shell 脚本 功能性语句 read,expr,test
1. read 从终端输入数据赋值给变量 read val 把读入的数据存放到val中 #!/bin/bash echo -n "please input two number :" ...
- JS对象 charAt() 方法可返回指定位置的字符。返回的字符是长度为 1 的字符串。
返回指定位置的字符 charAt() 方法可返回指定位置的字符.返回的字符是长度为 1 的字符串. 语法: stringObject.charAt(index) 参数说明: 注意:1.字符串中第一个字 ...
- c_数据结构_哈希表
#include <stdio.h> #include <stdlib.h> #include <string.h> #define ERROR 0 #define ...
- bootsrap-----固定布局解析
<div class="container"> container </div> .container { .container-fixed();容器的wi ...
- scala中类的简单使用记录
import scala.collection.mutable.ArrayBuffer /** * scala 中内部类的使用 */ class Classes { class Stu(name:St ...
- 概率dp——hdu4089推公式+循环迭代
迭代是化简公式的常用技巧 dp[i][j]表示队伍中有i人,tomato排在第j位出现情况2的概率,那么先推出公式再进行简化 dp[i][1]=p21*dp[i][i] + p41 j<=k : ...
- memcpy函数实现中的优化
今天浏览Google面试题的时候,有看到一个memcpy的实现,以及如何去优化memcpy. 我对memcpy的实现的记忆就是,拷贝的时候需要从后往前拷贝,为何防止内存重叠. 但是如果去优化它我没有想 ...