- <?php
- /**
- * 圖片特徵 Hash 計算
- *
- * @version $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax $
- * @author jax.hu
- *
- * <code>
- * //Sample_1
- * $hashA = ImageHash::pHash('001.jpg');
- * $hashB = ImageHash::pHash('002.jpg');
- * if(ImageHash::isSimilar($hashA, $hashB)){
- *
- * }
- *
- * </code>
- */
- class ImageHash {
- /**讀取圖片至指定大小*/
- public static function readImageTo($imagePath, $width, $height){
- if(!$imagePath || !file_exists($imagePath)){ return null; }
- if(class_exists('Imagick')){
- $image = new Imagick($imagePath);
- $image->thumbnailImage($width, $height);
- $img = imagecreatefromstring($image->getImageBlob());
- $image->destroy(); $image = null;
- }else{
- $createFunc = array(
- IMAGETYPE_GIF =>'imageCreateFromGIF',
- IMAGETYPE_JPEG =>'imageCreateFromJPEG',
- IMAGETYPE_PNG =>'imageCreateFromPNG',
- IMAGETYPE_BMP =>'imageCreateFromBMP',
- IMAGETYPE_WBMP =>'imageCreateFromWBMP',
- IMAGETYPE_XBM =>'imageCreateFromXBM',
- );
- $type = exif_imagetype($imagePath);
- if(!array_key_exists($type, $createFunc)){ return null; }
- $func = $createFunc[$type];
- if(!function_exists($func)){ return null; }
- $src = $func($imagePath);
- $img = imageCreateTrueColor($width, $height);
- imageCopyResized(
- $img, $src,
- 0,0,0,0,
- $width, $height, imagesX($src),imagesY($src)
- );
- imagedestroy($src);
- }
- return $img;
- }
- /**取得灰階數值*/
- public static function getGray($img,$x,$y){
- $col = imagecolorsforindex($img, imagecolorat($img,$x,$y));
- return intval($col['red']*0.3 + $col['green']*0.59 + $col['blue']*0.11);
- }
- /**取得 DCT 常數*/
- private static $_dctConst = null;
- public static function getDctConst(){
- if(self::$_dctConst){ return self::$_dctConst;}
- self::$_dctConst = array();
- for ($dctP=0; $dctP<8; $dctP++) {
- for ($p=0;$p<32;$p++) {
- self::$_dctConst[$dctP][$p] =
- cos( ((2*$p + 1)/64) * $dctP * pi() );
- }
- }
- return self::$_dctConst;
- }
- /**圖片檔案 aHash
- * @param string $filePath 檔案位址路徑
- * @return string 圖片 hash 值,失敗則是 null
- * */
- public static function aHash($imagePath){
- $img = self::readImageTo($imagePath, 8, 8);
- if(!$img){ return null; }
- $graySum = 0;
- $grays = array();
- for ($y=0; $y<8; $y++){
- for ($x=0; $x<8; $x++){
- $gray = self::getGray($img,$x,$y);
- $grays[] = $gray;
- $graySum += $gray;
- }
- }
- imagedestroy($img);
- /*計算所有像素的灰階平均值*/
- $average = $graySum/64;
- /*計算 hash 值*/
- foreach ($grays as $i => $gray){
- $grays[$i] = ($gray>=$average) ? '1' : '0';
- }
- return join('',$grays);
- }
- /**圖片檔案 pHash
- * @param string $filePath 檔案位址路徑
- * @return string 圖片 hash 值,失敗則是 null
- * */
- public static function pHash($imagePath){
- $img = self::readImageTo($imagePath, 32, 32);
- if(!$img){ return null; }
- /*取得灰階數值 32*32*/
- $grays = array();
- for ($y=0; $y<32; $y++){
- for ($x=0; $x<32; $x++){
- $grays[$y][$x] = self::getGray($img,$x,$y);
- }
- }
- imagedestroy($img);
- /*計算 DCT 8*8*/
- $dctConst = self::getDctConst();
- $dctSum = 0;
- $dcts = array();
- for ($dctY=0; $dctY<8; $dctY++) {
- for ($dctX=0; $dctX<8; $dctX++) {
- $sum = 1;
- for ($y=0;$y<32;$y++) {
- for ($x=0;$x<32;$x++) {
- $sum +=
- $dctConst[$dctY][$y] *
- $dctConst[$dctX][$x] *
- $grays[$y][$x];
- }
- }
- /*apply coefficients*/
- $sum *= .25;
- if ($dctY == 0 || $dctX == 0) {
- $sum *= 1/sqrt(2);
- }
- $dcts[] = $sum;
- $dctSum += $sum;
- }
- }
- /*計算所有像素的灰階平均值*/
- $average = $dctSum/64;
- /*計算 hash 值*/
- foreach ($dcts as $i => $dct){
- $dcts[$i] = ($dct>=$average) ? '1' : '0';
- }
- return join('',$dcts);
- }
- /**圖片檔案 dHash
- * @param string $filePath 檔案位址路徑
- * @return string 圖片 hash 值,失敗則是 null
- * */
- public static function dHash($imagePath){
- $img = self::readImageTo($imagePath, 9, 8);
- if(!$img){ return null; }
- $grays = array();
- for ($y=0; $y<8; $y++){
- for ($x=0; $x<9; $x++){
- $grays[$y][$x] = $gray = self::getGray($img,$x,$y);
- }
- }
- imagedestroy($img);
- $bitStr = array();
- for ($y=0; $y<8; $y++){
- for ($x=0; $x<8; $x++){
- $bitStr[] = ($grays[$y][$x] < $grays[$y][$x+1]) ? '1' : '0';
- }
- }
- return join('',$bitStr);
- }
- /**比較兩個 hash 值,是不是相似
- * @param string $aHash A圖片的 hash 值
- * @param string $bHash B圖片的 hash 值
- * @return bool 當圖片相似則回傳 true,否則是 false
- * */
- public static function isSimilar($hashStrA, $hashStrB){
- $aL = strlen($hashStrA); $bL = strlen($hashStrB);
- if ($aL !== $bL){ return false; }
- /*計算兩個 hash 值的漢明距離*/
- $distance = 0;
- for($i=0; $i<$aL; $i++){
- if ($hashStrA{$i} !== $hashStrB{$i}){ $distance++; }
- }
- return ($distance <= 10) ? true : false;
- }
- }
2013-05-20 22:41
[PHP] aHash, pHash, dHash 實做
相關文章 :
訂閱:
張貼留言 (Atom)
3 回應:
厲害的人...我是路過的,也是本行資訊人,您的文章很不錯,我會加RSS的
感謝支持!
博主,您好,这些hash可以做在另一个图像中包含给定的图像吗
張貼留言