2010-10-06 207 views
9

(A類似的問題已經被問對超級用戶與應用程序相關的答案。問題是張貼在這裏收集了相同的可編程解決方案)自動人臉檢測

在我的工作將護照尺寸的照片一起掃描,然後剪切成單獨的照片並用唯一的文件編號保存。目前我們使用Paint.net手動選擇,剪切和保存圖片。

樣品掃描的文檔的Picasa截圖: (來自:谷歌圖像搜索多個數據源,fairuse)

picasa screenshot

對於例如。在Picasa 3.8中,單擊視圖>人員時,會顯示所有人臉,並要求我爲他們命名,我是否可以將這些個人圖片自動保存爲不同圖片的名稱?

更新

所有我想要做的就是上面的轉換對單張照片的畫面。

在上面的圖片中,我已經展示了Picasa 3.8如何檢測圖像並提示我命名它們。我不需要臉部識別,我只需要臉部識別。 Picasa會檢測單個圖像並在RHS上顯示它們。這些個人圖像是我需要的。 Picasa創建一個.ini文件,該文件保存包含各個面的座標的十六進制值。

這些個人面孔是我感興趣的如果我可以有座標,我可以從圖片中裁剪所需的圖像。

SAMPLE.jpg

sample.jpg

INI內容

[SAMPLE.jpg] 
faces=rect64(c18f4c8ef407851e),d4ff0a020be5c3c0;rect64(534a06d429ae627),dff6163dfd9d4e41;rect64(b9c100fae46b3046),e1059dcf6672a2b3;rect64(7b5105daac3a3cf4),4fc7332c107ffafc;rect64(42a036a27062a6c),ef86c3326c143248;rect64(31f4efe3bd68fd8),90158b3d3b65dc9b;rect64(327904e0614d390d),43cbda6e92fcb63e;rect64(4215507584ae9b8c),15b6a967e857f334;rect64(895d4efeb8b68425),5c4ff70ac70b27d3 
backuphash=3660 

* ini文件似乎是保存面子標籤的座標爲rect64(534a06d429ae627),dff6163dfd9d4e41每個標籤。 從Picasa Help Site用戶Technonath引述說

@oedious寫道: - 這將是 有些技術性的,所以堅持下去。 *包含在rect64()中的數字是一個64位的十六進制數。 *將其分成四個16位數字。 *將每個數除以最大無符號16位數(65535),並且您將有 四個數字,介於0和1之間。 *剩餘的四個數字將爲您提供相對座標 矩形:(左,上,右,底部)。 *如果您想要以絕對座標結束,請將圖像寬度和頂部 的左側和右側多餘,然後按圖像高度底部。

上面的引用談到了rect64()中包含的數字,逗號後的圓括號之外的數字是什麼?

我已經問了一個相關的問題。其中的答案也可以幫助你。 Get four 16bit numbers from a 64bit hex value

注: INI細節其PICASA用於特定圖像生成 相同。

此問題已更新多次,可能不夠清楚。

有在Picasa Help site,在那裏我問同樣的問題 一位來自該線程的答案,我們將根據從ini文件中的十六進制值座標的一些迴應。以下代碼位於幫助站點的esac的C#中。我可以在PHP中執行相同的操作嗎?

public static RectangleF GetRectangle(string hashstr) 
{ 
    UInt64 hash = UInt64.Parse(hashstr, System.Globalization.NumberStyles.HexNumber); 
    byte[] bytes = BitConverter.GetBytes(hash); 

    UInt16 l16 = BitConverter.ToUInt16(bytes, 6); 
    UInt16 t16 = BitConverter.ToUInt16(bytes, 4); 
    UInt16 r16 = BitConverter.ToUInt16(bytes, 2); 
    UInt16 b16 = BitConverter.ToUInt16(bytes, 0); 

    float left = l16/65535.0F; 
    float top = t16/65535.0F; 
    float right = r16/65535.0F; 
    float bottom = b16/65535.0F; 

    return new RectangleF(left, top, right - left, bottom - top); 
} 

PHP代碼試圖轉換到64位的數字1和0剩餘1之間

<?php 
$dim = getimagesize("img.jpg");  
$hex64=array(); 
$b0="c18f4c8ef407851e"; 
$hex64[]=substr($b0,0,4); 
$hex64[]=substr($b0,4,4); 
$hex64[]=substr($b0,8,4); 
$hex64[]=substr($b0,12,4); 
$width=$dim[0]; 
$height=$dim[1]; 
foreach($hex64 as $hex16){ 
$dec=hexdec($hex16); 
$divide=65536; 
$mod=$dec%$divide; 
$result=$dec/$divide; 
$cordinate1=$result*$width; 
$cordinate2=$result*$height; 
echo "Remainder 1 : ".$mod." ; Result 1 : ".$result."<br/>CO-ORDINATES : <B>".$cordinate1." ".$cordinate2."</B><br/>"; 
} 
?> 

輸出

:49551;結果1: 0.75608825683594副標題:371.99542236328 396.94633483887剩餘1:19598;結果1: 0.29904174804688副標題:147.12854003906 156.99691772461剩餘1:62471;結果1: 0.95323181152344 CO-ORDINATES:468.99005126953 500.4467010498剩餘1:34078;結果1: 0.51998901367188座標:255.83459472656 272.99423217773

所以我有座標也和@Nirmal有shown how to crop them。現在接下來的步驟是解析picasa.ini中的十六進制代碼和文件名並整合代碼。 Picasa目前不通過api提供十六進制代碼(或Do they?)。如果是這樣,事情會更好。

所以我們正在接近一個解決方案。謝謝大家,我希望我能把賞金獎勵給大家(我不能,但不要害怕,並且不要在你的代表中出現尖峯!)

+0

你可以給所有四個角的'(x,y)'格式的最終​​座標嗎? – Nirmal 2010-10-14 07:56:52

+0

@Nirmal(371,156),(468,156),(468,272),(371,272) – abel 2010-10-14 08:25:35

回答

2

要回答這個問題的Picasa,看到Picasa的論壇上這樣迴應:
http://www.google.com/support/forum/p/Picasa/thread?tid=36ae553a7b49088e&hl=en

@oedious寫道: - 這將是 有些技術性的,所以堅持下去。 *包含在rect64()中的數字是一個64位的十六進制數。 *將其分成四個16位數字。 *將每個數除以最大無符號16位數(65535),並且您將有 四個數字,介於0和1之間。 *剩餘的四個數字將爲您提供相對座標 矩形:(左,上,右,底部)。 *如果您想要以絕對座標結束,請將圖像寬度和頂部 的左側和右側多餘,然後按圖像高度底部。

+0

這是一個寶貴的鏈接。謝謝。如果你已經理解了我的問題,我試圖將掃描後的img分解爲單個imgs。如果我有座標,我可以爲Paint.net編寫一個插件,它可以做到這一點(我沒有任何桌面編程經驗,所以這可能需要幾個月的時間,當它完成後會發佈一個鏈接:)。) – abel 2010-10-08 15:29:27

+0

我如何從64位的一個16位數字? – abel 2010-10-08 15:35:13

2

你可以進一步簡化問題:-)如果掃描的圖像將總是在一個5x4的網格...然後你可以很容易只是在任何提供位圖操作的編程語言中打開圖像,並保存每個正方形。這裏有一個如何用C#做這樣一個例子:

private Image Crop(Image pics, Rectangle area) 
{ 
    var bitmap = new Bitmap(pics); 
    return (Image)bitmap.Clone(area, bitmap.PixelFormat); 
} 

所有你需要做的是計算每個矩形,然後調用該方法返回由矩形定義的圖像的只是區域。喜歡的東西(可能是僞代碼,沒有編譯下面的代碼):

// assuming that each sub image in the larger is 45x65 
int cellwidth=45, cellheight=65; 

for(int row=0;row<5;row++) 
{ 
    for(int col=0;col<4;col++) 
    { 
    var rect = new Rectangle(
     row * cellwidth, 
     col * cellheight, 
     cellwidth, 
     cellheight); 
    var picture = Crop(bigPicture, rect); 
    // then save the sub image with whatever naming convention you need 
    } 
} 
+0

但護照照片大小各不相同。一些是5釐米乘4釐米,一些4乘3釐米,4x4等,並將它們放置在掃描儀中通常會造成隨意安排。如果我可以檢測圖像的標記部分,然後裁剪出來...我可以做一些PHP。 – abel 2010-10-06 12:12:06

+0

我已經更新了原來的問題,如果我可以有座標,你的解決方案看起來似乎是合理的。但座標是在十六進制,我不明白十六進制, – abel 2010-10-12 17:12:51

5

OpenCV - 中附帶的分佈是人臉檢測的例子之一。

+0

謝謝我會考慮它 – abel 2010-10-06 12:21:04

+1

我正在尋找這樣一個圖書館很長一段時間,看起來像這會幫助。感謝分享。 – Nirmal 2010-10-18 06:41:58

5

你對這個問題的解決方法是矯枉過正。忽略臉部。你有什麼是堅實的白色背景和一堆矩形圖像。所有你需要做的是找到包圍每個圖像和裁剪的矩形。

首先在標記所有非背景像素的原始圖像上運行過濾器。這將需要一些調整,因爲有時背景會有一點色調(污垢)或照片將有一些看起來像背景像素(真的是白色的牙齒)。

現在,您可以查看其中沒有背景色的大面積區域。將它們裁剪成矩形。

既然你是一個正在做掃描的人,爲什麼不讓背景變成綠色?綠色可能是一種更容易過濾的顏色,特別是因爲護照照片是在白色背景上拍攝的。

+0

+1讓我以不同的角度看待問題。製作綠色背景將非常簡單,我期待開發一個php webapp,它將在本地服務器上運行,該服務器將掃描的img作爲上傳文件,然後將各個照片保存在服務器上,並將其作爲一個zip下載。有沒有PHP libs(gd?)這將允許我檢測顏色和選擇rects? – abel 2010-10-13 11:45:09

+0

我不知道是否有庫。但是,必須有庫才能加載圖像並處理其中的顏色。從背景開始,如綠色> 90%,紅色和藍色<10%。然後尋找一個長方形孔的綠色地帶。 (下載GIMP並使用魔術棒工具查看我的意思。)搜索孔的邊緣並將其變爲矩形。第二部分有點困難,但有技巧http://en.wikipedia.org/wiki/Hough_transform。如果您知道矩形與頁面的兩側成直角,則會有所幫助。 – Eyal 2010-10-13 13:41:36

+0

我已經更新了這個問題。用一個php腳本獲取(?)圖像座標。我可以使用這些從圖像中裁剪單個圖像嗎? – abel 2010-10-13 17:52:38

1

對於裁剪的部分,我打字未經測試的代碼,但這應該工作:

<?php 
//source image 
$srcImg = "full/path/of/source/image.jpg"; 
//output image 
$outImg = "full/path/to/result/image.jpg"; 

//coordinates obtained from your calculation 
$p1 = array('X'=>371, 'Y'=>156); 
$p2 = array('X'=>468, 'Y'=>156); 
$p3 = array('X'=>468, 'Y'=>272); 
$p4 = array('X'=>371, 'Y'=>272); 

//let's calculate the parametres 
$srcX = $p1['X']; 
$srcY = $p1['Y']; 
$width = $p2['X'] - $p1['X']; 
$height = $p4['Y'] - $p1['Y']; 

//image processing 
$srcImg = imagecreatefromjpeg($srcImg); 
$dstImg = imagecreatetruecolor($width, $height); 
imagecopy($dstImg, $srcImg, 0, 0, $srcX, $srcY, $width, $height); 
imagejpeg($dstImg, $outImg, 100); // 100 for highest quality, 0 for lowest quality 
imagedestroy($dstImg); 
?> 

上面的代碼假定您的源圖像是JPEG格式和座標做一個完美的矩形或正方形。

希望有所幫助。

+0

謝謝你nirmal。我正在探索PHP的圖像處理庫。豎起大拇指! – abel 2010-10-14 11:39:23

+0

不客氣。很高興有幫助。 – Nirmal 2010-10-18 06:21:09

1

這應該讓你越過終點線。這裏有一些解析INI的代碼。

<?php 
$vals = parseIni('picasa.ini'); 
foreach($vals as $filename => $values) { 
    $rects = getRects($values['faces']); 
    foreach($rects as $rect) { 
     printImageInfo($filename, $rect); 
    } 
} 

/** 
* PHP's own parse_ini_file doesn't like the Picasa format. 
*/ 
function parseIni($file) 
{ 
    $index = 0; 
    $vals = array(); 
    $f = fopen($file, 'r'); 
    while(!feof($f)) { 
     $line = trim(fgets($f)); 
     if (preg_match('/^\[(.*?)\]$/', $line, $matches)) { 
      $index = $matches[1]; 
      continue; 
     } 

     $parts = explode('=', $line, 2); 
     if (count($parts) < 2) continue; 
     $vals[$index][$parts[0]] = $parts[1]; 
    } 

    fclose($f); 
    return $vals; 
} 

function getRects($values) 
{ 
    $values = explode(';', $values); 
    $rects = array(); 
    foreach($values as $rect) { 
     if (preg_match('/^rect64\(([^)]+)\)/', $rect, $matches)) { 
      $rects[] = $matches[1]; 
     } 
    } 

    return $rects; 
} 

function printImageInfo($filename, $rect) 
{ 
    $dim = getimagesize($filename);  
    $hex64=array(); 
    $hex64[]=substr($rect,0,4); 
    $hex64[]=substr($rect,4,4); 
    $hex64[]=substr($rect,8,4); 
    $hex64[]=substr($rect,12,4); 
    $width=$dim[0]; 
    $height=$dim[1]; 
    foreach($hex64 as $hex16){ 
     $dec=hexdec($hex16); 
     $divide=65536; 
     $mod=$dec%$divide; 
     $result=$dec/$divide; 
     $cordinate1=$result*$width; 
     $cordinate2=$result*$height; 
     echo "Remainder 1 : ".$mod." ; Result 1 : ".$result."<br/>CO-ORDINATES : <B>".$cordinate1." ".$cordinate2."</B><br/>"; 
    } 
} 
1

我在.NET中開發了一個小應用程序,它完全按照您的說法生成臉部文件。看看這裏:http://ceottaki.com/devprojects/getpicasafaces

源代碼也可用。

雖然我還沒有實現正從他們的十六進制代碼的聯繫人的姓名,也可以使用谷歌聯繫人API:http://code.google.com/apis/contacts/

隨着該API就可以得到由ID接觸,如果你的聯繫人在Picasa和Google通訊錄之間同步,十六進制ID是相同的。

完整聯繫人鏈接的最後一部分是Picasa使用的十六進制。

我希望這會有所幫助。

乾杯, Felipe。

+1

好的工作!沒有想到聯繫人整合;這是一個附加。儘管取決於Picasa獲得rect格式是痛苦的。希望有一個API! – abel 2011-03-09 13:42:28