Exemple #1
0
 public static function imageDenoise(&$image, $sizeX, $sizeY)
 {
     // 初始化
     self::$image = $image;
     self::$visit = array_fill(0, 120, array_fill(0, 60, FALSE));
     self::$denoised = self::$visit;
     self::$sizeX = $sizeX;
     self::$sizeY = $sizeY;
     // 去噪
     for ($x = 0; $x < $sizeX; $x++) {
         for ($y = 0; $y < $sizeY; $y++) {
             if (!self::$visit[$x][$y] && self::$image[$x][$y] != 255) {
                 $size = self::getBlockSize($x, $y, 0);
                 // 求块大小
                 if ($size < 10) {
                     // 根据块大小判断噪点簇
                     self::deletePixel($x, $y);
                 }
             }
         }
     }
     return self::$image;
 }
 /**
  * 处理图片 去噪 二值化
  * @param  string $fileName 验证码图片路径
  * @return array            四个字符的二进制矩阵
  */
 function processImage($fileName)
 {
     $backgroundColor = array(212, 218, 219, 252, 209, 216);
     $sizeX = 120;
     $sizeY = 60;
     $res = imagecreatefromgif($fileName);
     $this->res = $res;
     $image = array();
     // 读颜色 去背景色
     for ($x = 0; $x < $sizeX; $x++) {
         for ($y = 0; $y < $sizeY; $y++) {
             $colorIndex = imagecolorat($res, $x, $y);
             $image[$x][$y] = $colorIndex;
             if (in_array($colorIndex, $backgroundColor)) {
                 $image[$x][$y] = 255;
             }
         }
     }
     // 去噪点
     $image = Denoise::imageDenoise($image, $sizeX, $sizeY);
     $columnPx = array();
     // 某列像素个数
     $charCol = array();
     // 字符的开始列和结束列
     $charFound = 0;
     // 当前正在查找的字符
     $finding = FALSE;
     // 扫描状态
     // 从左向右扫描 字符左右位置
     for ($x = 0; $x < $sizeX; $x++) {
         $columnPx[$x] = 0;
         for ($y = 0; $y < $sizeY; $y++) {
             if ($image[$x][$y] != 255) {
                 $columnPx[$x]++;
             }
         }
         // 如果正在扫描字符,此列没有出现点则结束正在扫描状态,
         // 记录结束列。如果不是在扫描状态,如果出现点,则记录
         // 字符开始列并转换状态。
         if ($finding) {
             if ($columnPx[$x] == 0) {
                 $finding = FALSE;
                 $charCol[$charFound++][1] = $x;
             }
         } elseif ($columnPx[$x] > 0) {
             $finding = TRUE;
             $charCol[$charFound][0] = $x;
         }
     }
     // 是否有粘连
     if (count($charCol) < 4) {
         for ($charNum = 0; $charNum < 4; $charNum++) {
             if ($charCol[$charNum][1] - $charCol[$charNum][0] > 30) {
                 // 字符宽大于30则分裂
                 for ($col = 3; $col > $charNum; $col--) {
                     if (isset($charCol[$col - 1])) {
                         $charCol[$col] = $charCol[$col - 1];
                     } else {
                         $charCol[$col] = array();
                     }
                 }
                 // 按照颜色分割字符
                 $avgWidth = ceil(($charCol[$charNum][0] + $charCol[$charNum][1]) / 2);
                 $divide = false;
                 for ($col = $avgWidth - 5; $col < $avgWidth + 5; $col++) {
                     $color1 = $this->averageRGB($image[$col]);
                     $color2 = $this->averageRGB($image[$col + 1]);
                     // 色差大于100则不同字符
                     if ($this->colorDistance($color1, $color2) > 100) {
                         $charCol[$charNum + 1][0] = $col + 1;
                         $charCol[$charNum][1] = $col + 1;
                         $divide = true;
                         break;
                     }
                 }
                 // 还没被分割则直接对半分
                 if (!$divide) {
                     $charCol[$charNum + 1][0] = $avgWidth;
                     $charCol[$charNum][1] = $avgWidth;
                 }
             }
         }
     }
     $charRow = array();
     // 从上到下扫描 字符上下位置
     for ($charNum = 0; $charNum < 4; $charNum++) {
         $charRow[$charNum] = array(-1, -1);
         for ($y = 0; $y < $sizeY; $y++) {
             for ($x = $charCol[$charNum][0]; $x < $charCol[$charNum][1]; $x++) {
                 if ($image[$x][$y] != 255) {
                     // 如果此行有点,上界没有值则存上界,已经有值则存下界
                     if ($charRow[$charNum][0] == -1) {
                         $charRow[$charNum][0] = $y;
                     } else {
                         $charRow[$charNum][1] = $y;
                     }
                     break;
                 }
             }
         }
         $charRow[$charNum][1]++;
         // 下界多加1,为与右界保持一致都是多1
     }
     // 二值化
     for ($x = 0; $x < $sizeX; $x++) {
         for ($y = 0; $y < $sizeY; $y++) {
             if ($image[$x][$y] == 255) {
                 $image[$x][$y] = 0;
             } else {
                 $image[$x][$y] = 1;
             }
         }
     }
     // 取出四个字符
     $char = array_fill(0, 4, array_fill(0, 625, 0));
     for ($charNum = 0; $charNum < 4; $charNum++) {
         $height = $charRow[$charNum][1] - $charRow[$charNum][0];
         $width = $charCol[$charNum][1] - $charCol[$charNum][0];
         // 最大尺寸25x25
         if ($height > 25) {
             $charRow[$charNum][1] = $charRow[$charNum][0] + 25;
         }
         if ($width > 25) {
             $charCol[$charNum][1] = $charCol[$charNum][0] + 25;
         }
         for ($y = 0; $y < $height; $y++) {
             for ($x = 0; $x < $width; $x++) {
                 $char[$charNum][$y * 25 + $x] = $image[$x + $charCol[$charNum][0]][$y + $charRow[$charNum][0]];
             }
         }
     }
     return $char;
 }