首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 圖像識別技術原理與實戰:從像素比對到驗證碼破解

     編輯:PHP 綜合知識

圖像識別聽起來很高深,但其核心邏輯與傳統密碼驗證並無二致:預先建立特徵庫 → 採集待識別資料 → 比對相似度。差別在於圖像識別引入容錯機制(如相似度 95% 即判定成功),而密碼驗證要求 100% 精確匹配。

專案背景與需求

早期某專案需識別圖片中固定位置的三位數字(如抽獎頁面的獎項數字)。最初考慮用 JS/Flash 遮罩層前端處理,但需求方強制要求 PHP 後端識別。恰逢當時新聞熱議馬雲人臉支付、12306 驗證碼被破解,遂深入研究 PHP 圖像識別實作。

核心流程:像素二值化 → 特徵提取 → 模板比對

1. 圖片載入與二值化

將 PNG 圖片載入 GD 資源,遍歷每個像素,根據 RGB 閾值(如 < 125 判定為前景)轉為 0/1 矩陣:

<?php
$res = imagecreatefrompng($path);
$size = getimagesize($path);
for ($y = 0; $y < $size[1]; ++$y) {
    for ($x = 0; $x < $size[0]; ++$x) {
        $rgb = imagecolorat($res, $x, $y);
        $rgba = imagecolorsforindex($res, $rgb);
        $data[$y][$x] = ($rgba['red'] < 125 || $rgba['green'] < 125 || $rgba['blue'] < 125) ? 1 : 0;
    }
}
?>

2. 橫向/縱向投影切割字符

掃描二值矩陣,按行/列投影找出字符邊界,切分單一字符區塊並正規化尺寸(如 17×11 像素)。

3. 模板庫建立與相似度比對

預先將 0-9 數字的標準字形轉為 0/1 字串存入陣列。識別時,將切分出的字符字串與模板庫逐一計算 similar_text() 相似度,超過 95% 即判定為該數字:

<?php
$templates = [
    '1' => '00000000111000000000000001110000000001001000100000000010100011000000000011000110000000000110000100000000010110011000000',
    '5' => '00000000001000000000000000010000000000100100100000000000101001110000000000100000110000000011000000100000001101000010000',
    // ... 其餘數字模板
];

function recognize($charStr, $templates) {
    foreach ($templates as $digit => $tpl) {
        similar_text($charStr, $tpl, $percent);
        if ($percent > 95) return $digit;
    }
    return '?';
}
?>

完整識別類實現(精簡版)

<?php
class DigitRecognizer {
    private $imgPath, $imgSize, $binData;

    public function __construct(string $path) { $this->imgPath = $path; }

    // 二值化
    public function binarize(): void {
        $res = imagecreatefrompng($this->imgPath);
        $this->imgSize = getimagesize($this->imgPath);
        for ($y = 0; $y < $this->imgSize[1]; ++$y) {
            for ($x = 0; $x < $this->imgSize[0]; ++$x) {
                $rgb = imagecolorat($res, $x, $y);
                $rgba = imagecolorsforindex($res, $rgb);
                $this->binData[$y][$x] = ($rgba['red'] < 125 || $rgba['green'] < 125 || $rgba['blue'] < 125) ? 1 : 0;
            }
        }
    }

    // 切割並識別指定 X 座標區域
    public function recognizeAt(int $x, int $y, int $w, int $h): string {
        $canvas = imagecreatetruecolor($w, $h);
        $white = imagecolorallocate($canvas, 255, 255, 255);
        imagefilledrectangle($canvas, 0, 0, $w, $h, $white);
        $src = imagecreatefrompng($this->imgPath);
        imagecopy($canvas, $src, 0, 0, $x, $y, $w, $h);
        $tmp = sys_get_temp_dir() . '/ocr_' . uniqid() . '.png';
        imagepng($canvas, $tmp);
        $this->imgPath = $tmp;
        $this->binarize();
        // 這裡簡化:直接將二值矩陣展平為字串比對
        $str = '';
        foreach ($this->binData as $row) $str .= implode('', $row);
        return $this->matchTemplate($str);
    }

    private function matchTemplate(string $str): string {
        // 同前方模板比對邏輯
    }
}
?>

安全啟示與防禦建議

此類基於模板比對的識別,原理上可破解早期固定字體、無干擾線的驗證碼(如舊版 12306)。現代防禦手段包括:

  • 字形隨機化:每次生成隨機字體、大小、旋轉、扭曲
  • 干擾元素:噪點、干擾線、背景紋理
  • 行為分析:滑軌驗證、點選驗證、設備指紋
  • 限流與風控:IP/設備/行為頻率限制

圖像識別技術本身中性,關鍵在於對抗雙方的技術迭代。開發者應採用成熟驗證碼服務(如 Google reCAPTCHA、Geetest)而非自建弱防禦方案。

原作者完整代碼參考

文末附上原作者 gjPhone 類完整實現(含縱向投影、調試輸出等),供深入研究參考。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved