程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP基礎知識 >> 簡單的驗證碼識別實現教程

簡單的驗證碼識別實現教程

編輯:PHP基礎知識
 

首先來看這張經典的驗證碼:
txsb

人腦可以主動過濾掉雜亂的背景,在識別的過程中也可以忽略掉那條很長的曲線,然後非常輕松地識別出四個字符:TXSb。

計算機拿到這張圖,它就2了。。。一個JPG文件,對計算機來說就是一堆2進制數據。還好JPG有自身的數據結構,可以按照相應算法讀取到圖片中每一個點的顏色。也就如此而已了。

顏色分布在 0x000000 ~ 0xFFFFFF(0xRGB), 數目眾多。為了把事情簡化,可以先對圖片進行灰度化處理,即把原有顏色轉化為灰色。 灰色其實也包含很多種顏色啦,而且灰色有一個特點,它的RGB三個值是相等的,比如000000, AAAAAA, 777777,FFFFFF , 當然黑色與白色是特殊的灰色。對於任意一個顏色,可以把它的RGB值加權平均,得到灰度:

$gray = round(.299*$red + .587*$green + .114*$blue);

gray

現在顏色只剩下256種了(00-FF),其實還可以更加簡化,簡化到只剩下白色與黑色。於是我們就要找到一個阈值(yu zhi, not fa zhi),如果顏色大於等於這個阈值,則標記為白色,否則標記為黑色。

尋找這個阈值,有一個現成的算法:Otsu’s method,可以參考

http://en.wikipedia.org/wiki/Otsu’s_method

binary

接下來,最好能去掉圖片中又細又長的那條線。還好它比較細。。否則下面的辦法就不靈了。
我們可以先把圖像裡面的黑色進行腐蝕,收縮(erosion),算法可以參考

http://homepages.inf.ed.ac.uk/rbf/HIPR2/erode.htm

腐蝕可以達到瘦身的效果,目的是把那條細長的曲線瘦身到基本消失。

erosion

曲線雖然被瘦身掉了,但是那4個字符也變得很虛弱,如果我們再按照瘦身的逆過程進行膨脹(dilation)操作,那麼這4個字符就又會基本上恢復原樣,同時細長的曲線還是保持基本消失狀態。
dilation

可見,先瘦身再膨脹,可以去掉圖片中的細線。 如果是粗線,那麼就是反效果了,4個字符被腐蝕掉,只留下了粗線。。。不多提這種情況了。

下一步,我們把每一塊連通的黑色點都標記為同一種顏色,算法可以參考

http://en.wikipedia.org/wiki/Connected-component_labeling

如果連通在一起的點少於某個阈值,無法構成字符,那麼這塊區域就不要了。

label

有一點悲劇的是,由於Sb是連接在一起的,所以被標記為同一種顏色。如何把這個Sb分隔開呢?
按照這篇論文的說法:

http://vps.graemebell.net/publications/upload/mta-hlbo10-preprint.pdf

我們可以把Sb上的非白色點向X軸進行投影(projection),投影中的最低點,就是S與b的分隔點。

projection_bad

可以看到S與b的區域內有二個低點。最右側的低點是因為b這個字符,中間是空的….所以,在投影之前,要先找到封閉的圖形區域,因為這些封閉區域會誤導投影最低點的選擇。

尋找封閉區域可以繼續使用上面的Connected component labeling,只是這次尋找的是連通的白色點。當然了,最大的一塊連通的白色點,是沒有必要進行標記的,就繼續讓它作為背景吧。

findclosed

然後進行投影:
projection

可以看到,Sb區域只有一個低點了。。就將其作為分隔點,重新標記顏色:
relabel

至此,就完成了字符分隔的過程。

然後如何識別各個字符呢?
簡單算法有 chain code:

http://www8.cs.umu.se/kurser/TDBC30/VT04/material/lect13_kap_11.pdf

輪廓很容易標記出來,但是與字模進行對比的時候,就會發現成功率不高。sigh…

show_chain_code_616351002

show_chain_code_677341415

show_chain_code_1461795077

show_chain_code_1715692701


<?PHP

assert_options (ASSERT_BAIL, 1);

class A {

private $src_file ; //原始文件

private $sourceImage; //gd讀取原始文件
private $img_width; //原始文件寬
private $img_height; //原始文件高

private $dst_file ; //輸出文件
private $projection_count = array(); //計算投影


private $labels_count = 0; //

CONST LABEL_THRESHOLD = 100; //低於LABEL_THRESHOLD個像素的點的聚集區域將被無視。
CONST SLIDE_WINDOW_SIZE = 5; //投影後用來尋找最低點。
CONST LABEL_4_NO = 4; //驗證碼文件中的字符個數...
CONST DILATION_EROSION_NO = 5; //腐蝕,膨脹原始圖片的次數。。
CONST DILATION_EROSION_NO_LEARN = 4; //腐蝕,膨脹學習圖片的次數。。

private $four_colors ;
private $old_four_colors = array(
0x0000FF, //blue
0x00FF00, //GREEN
0x0EFCF2, //light blue
0xFF0000, //RED
0xFC0EE9, //purple
0xFCF20E, //BROWN
); //幾個預設的顏色。

private $closed_color = 0xFC770E; //用來填充封閉區域的顏色。

private $segment_lines = array(
); //圖片的分割情況
private $segment_lines2 = array(
); //圖片的各個分割線.

private $learn_sequence_array = array(); //學習圖片的chain code.

public function __construct($src_file) {
$this->four_colors = $this->old_four_colors;

//學習文件。
$this->learn();


$this->src_file = $src_file;

$this->sourceImage = imagecreatefromjpeg($src_file);
// get image dimensions
$this->img_width = imageSX($this->sourceImage);
$this->img_height = imageSY($this->sourceImage);

//灰度化
$this->grayScale();
$this->dst_file = "./gray.jpg";
$this->o();

//單色化
$this->binarization();
$this->dst_file = "./binary.jpg";
$this->o();

//瘦身 , 腐蝕
for($i=0;$i<self::DILATION_EROSION_NO;$i++) {
$this->erosion($this->sourceImage, $this->img_width, $this->img_height);
}
$this->dst_file = "./erosion.jpg";
$this->o();

//膨脹
for($i=0;$i<self::DILATION_EROSION_NO;$i++) {
$this->dilation($this->sourceImage, $this->img_width, $this->img_height);
}
$this->dst_file = "./dilation.jpg";
$this->o();


//把互相連接的點標記為同一種顏色。
$this->label();
$this->dst_file = "./label.jpg";
$this->o();

//按顏色變化,分割原始圖片為多塊。
$this->segment();

//投影
$this->projection();
$this->dst_file = "./projection_bad.jpg";
$this->projection_o();

//尋找封閉區域。
$this->findClosed();
$this->dst_file = "./findclosed.jpg";
$this->o();


//投影
$this->projection();
$this->dst_file = "./projection.jpg";
$this->projection_o();

//根據投影重新對字符進行顏色標記並分割。
$this->relabel();
$this->dst_file = "./projection_relabel.jpg";
$this->projection_o();

$this->dst_file = "./relabel.jpg";
$this->o();


//對每一塊進行識別。
$this->recognition();
}


/**
* 參考 http://kr1.php.net/manual/en/function.imagecopymergegray.php
*/
private function grayScale() {
print __FUNCTION__.PHP_EOL;

// convert to grayscale
// note: this will NOT affect your original image, unless
// originalFileName and destinationFileName are the same
for ($y = 0; $y <$this->img_height; $y++) {
for ($x = 0; $x <$this->img_width; $x++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
$red = ($rgb >> 16) & 0xFF;
$green = ($rgb >> 8) & 0xFF;
$blue = $rgb & 0xFF;

$gray = round(.299*$red + .587*$green + .114*$blue);

// shift gray level to the left
$grayR = $gray << 16; // R: red
$grayG = $gray << 8; // G: green
$grayB = $gray; // B: blue

// OR operation to compute gray value
$grayColor = $grayR | $grayG | $grayB;

// set the pixel color
imagesetpixel ($this->sourceImage, $x, $y, $grayColor);
//imagecolorallocate ($sourceImage, $gray, $gray, $gray);
}
}

}

private function binarization() {
print __FUNCTION__.PHP_EOL;
$histogram = array_pad(array(), 256, 0);
for ($y = 0; $y <$this->img_height; $y++) {
for ($x = 0; $x <$this->img_width; $x++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
$red = ($rgb >> 16) & 0xFF;
$green = ($rgb >> 8) & 0xFF;
$blue = $rgb & 0xFF;

assert($red == $green);
assert($green == $blue);

$histogram[$blue] ++;
}
}

$level = $this->otsu($histogram, $x * $y);


for ($y = 0; $y <$this->img_height; $y++) {
for ($x = 0; $x <$this->img_width; $x++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
$blue = $rgb & 0xFF;

if ($blue >= $level) {
$new_color = 0xFFFFFF;
} else {
$new_color = 0;
}
imagesetpixel($this->sourceImage, $x, $y, $new_color);

}
}

}


/**
* 參考 http://en.wikipedia.org/wiki/Otsu's_method
*/
private function otsu($histogram, $total) {
print __FUNCTION__.PHP_EOL;
$sum = 0;
for ($i = 1; $i < 256; ++$i)
$sum += $i * $histogram[$i];
$sumB = 0;
$wB = 0;
$wF = 0;
$mB;
$mF;
$max = 0.0;
$between = 0.0;
$threshold1 = 0.0;
$threshold2 = 0.0;
for ($i = 0; $i < 256; ++$i) {
$wB += $histogram[$i];
if ($wB == 0)
continue;
$wF = $total - $wB;
if ($wF == 0)
break;
$sumB += $i * $histogram[$i];
$mB = $sumB / $wB;
$mF = ($sum - $sumB) / $wF;
$between = $wB * $wF * pow($mB - $mF, 2);
if ( $between >= $max ) {
$threshold1 = $i;
if ( $between > $max ) {
$threshold2 = $i;
}
$max = $between;
}
}
return ( $threshold1 + $threshold2 ) / 2.0;
}


private function o() {
print __FUNCTION__.PHP_EOL;

// copy pixel values to new file buffer
$destinationImage = ImageCreateTrueColor($this->img_width, $this->img_height);
imagecopy($destinationImage, $this->sourceImage, 0, 0, 0, 0, $this->img_width, $this->img_height);

// create file on disk
imagejpeg($destinationImage, $this->dst_file);

// destroy temp image buffers
imagedestroy($destinationImage);
//imagedestroy($this->sourceImage);

}


/**
* 參考: http://homepages.inf.ed.ac.uk/rbf/HIPR2/erode.htm
*/
private function erosion($sourceImage, $img_width, $img_height) {
print __FUNCTION__.PHP_EOL;

$tmp_image= ImageCreateTrueColor($img_width, $img_height);

for ($y = 0; $y <$img_height; $y++) {
for ($x = 0; $x <$img_width; $x++) {
//檢查上下左右八個點是否都為0
imagesetpixel($tmp_image, $x, $y, 0xFFFFFF);

$rgb_old = imagecolorat($sourceImage, $x, $y);

$count = 0;
for($yy=$y; $yy<=$y+1&& $yy>=0&&$yy<$img_height; $yy++) {
//for($xx = $x-1; $xx<=$x+1 && $xx>=0&&$xx<$img_width; $xx++) {
$xx = $x;
$rgb = imagecolorat($sourceImage, $xx, $yy);
if ($rgb == 0xFFFFFF) {
$count ++;
break;
} else {
}
//}
}
if ($count == 0)
imagesetpixel($tmp_image, $x, $y, 0);

/**
if ($count !=0 && $rgb_old == 0xFFFFFF) {
print 'erased'.PHP_EOL;
}
**/
}
}

imagecopy($sourceImage, $tmp_image, 0, 0, 0, 0, $img_width, $img_height);
imagedestroy($tmp_image);

}


/**
* 參考: http://homepages.inf.ed.ac.uk/rbf/HIPR2/dilate.htm
*/
private function dilation($sourceImage, $img_width, $img_height) {
print __FUNCTION__.PHP_EOL;
$tmp_image= ImageCreateTrueColor($img_width, $img_height);

for ($y = 0; $y <$img_height; $y++) {
for ($x = 0; $x <$img_width; $x++) {
imagesetpixel($tmp_image, $x, $y, 0xFFFFFF);

$rgb_old = imagecolorat($sourceImage, $x, $y);

$count = 0;
for($yy=$y; $yy<=$y+1&& $yy>=0&&$yy<$img_height; $yy++) {
//for($xx = $x-1; $xx<=$x+1 && $xx>=0&&$xx<$img_width; $xx++) {
$xx = $x;
$rgb = imagecolorat($sourceImage, $xx, $yy);
if ($rgb == 0) {
$count ++;
break;
} else {
}
//}
}
if ($count != 0)
imagesetpixel($tmp_image, $x, $y, 0);

/**
if ($count !=0 && $rgb_old == 0xFFFFFF) {
print 'erased'.PHP_EOL;
}
**/
}
}

imagecopy($sourceImage, $tmp_image, 0, 0, 0, 0, $img_width, $img_height);
imagedestroy($tmp_image);
}



/**
* 參考 http://en.wikipedia.org/wiki/Connected-component_labeling
*/

private function label() {
print __FUNCTION__.PHP_EOL;
$linked = array();
$labels = array();
$next_label = 0;
for ($y = 0; $y <$this->img_height; $y++) {
for ($x = 0; $x <$this->img_width; $x++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
if ($rgb == 0xFFFFFF) continue;

$neighbors = array();

//north
$xx = $x;
$yy = $y -1;
if ($yy >=0) {
$rgb = imagecolorat($this->sourceImage, $xx, $yy);
if ($rgb == 0) {
$neighbors[] = $labels[$yy][$xx];
}
}


//west
$xx = $x-1;
$yy = $y;
if ($xx >=0) {
$rgb = imagecolorat($this->sourceImage, $xx, $yy);
if ($rgb == 0) {
$neighbors[] = $labels[$yy][$xx];
}
}

//north-west
$xx = $x-1;
$yy = $y-1;
if ($xx >=0 && $yy >=0) {
$rgb = imagecolorat($this->sourceImage, $xx, $yy);
if ($rgb == 0) {
$neighbors[] = $labels[$yy][$xx];
}
}

//north-east
$xx = $x+1;
$yy = $y-1;
if ($xx <$this->img_width && $yy >=0) {
$rgb = imagecolorat($this->sourceImage, $xx, $yy);
if ($rgb == 0) {
$neighbors[] = $labels[$yy][$xx];
}
}

$neighbors = array_unique($neighbors);

if (empty($neighbors)) {
//$linked[$next_label] = array();
$linked[$next_label] = array($next_label);
$labels[$y][$x] = $next_label;
$next_label ++;
} else {
$labels[$y][$x] = min($neighbors);

foreach($neighbors as $v) {
$linked[$v] = array_unique(array_merge($linked[$v], $neighbors));
}
#$linked[$labels[$y][$x]] = array_unique(array_merge($linked[$v], $neighbors));
}


}
}


$distinct_labels = array();
for ($y = 0; $y <$this->img_height; $y++) {
for ($x = 0; $x <$this->img_width; $x++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
if ($rgb == 0) {
//這裡不能直接用min(), 需要遞歸下去,找到最小值。
$l = $labels[$y][$x] = $this->findMin($linked, $labels[$y][$x] );

if (isset($distinct_labels[$l]))
$distinct_labels[$l]++;
else
$distinct_labels[$l] = 0;
}
}
}


arsort($distinct_labels, SORT_NUMERIC );
#print_r($distinct_labels);
/**
Array
(
[0] => 1242
[9] => 302
[7] => 233
[1] => 11
[13] => 5
[2] => 5
)
**/


//$available_labels = array_flip(array_keys(array_slice($distinct_labels, 0, 4, TRUE)));

//需要一個阈值, 去掉比較少的label.

$available_labels = array();
foreach($distinct_labels as $l=>$______) {
if ($______ < self::LABEL_THRESHOLD) {
break;
}

$available_labels[] = $l;
}


$available_labels = array_flip($available_labels);

assert( count($available_labels) <= 4);

$this->labels_count = count($available_labels);

//what to do if big than 4??

$this->four_colors = array_slice($this->four_colors, 0, count($available_labels));
//print_r($available_labels);die();
for ($y = 0; $y <$this->img_height; $y++) {
for ($x = 0; $x <$this->img_width; $x++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
if ($rgb == 0xFFFFFF) continue;

if (isset($available_labels[ $labels[$y][$x] ]) ) {
imagesetpixel($this->sourceImage, $x, $y, $this->four_colors[$available_labels[ $labels[$y][$x] ] ]);
} else {
imagesetpixel($this->sourceImage, $x, $y, 0xFFFFFF);
}
}
}



}

private function findMin($linked, $label) {
$old = -1;
while(1) {

$label = min($linked[$label]);
if ($label == $old) {
return $label;
}

$old = $label;
}
}


private function findClosed() {
print __FUNCTION__.PHP_EOL;
//找出$this->projection_image中全部連通的背景點。
//找出其中最大面積。
//比最大面積小的連通點,就是closed region.
$linked = array();
$labels = array();
$next_label = 0;
for ($y = 0; $y <$this->img_height; $y++) {
for ($x = 0; $x <$this->img_width; $x++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
if ($rgb != 0xFFFFFF) continue;

$neighbors = array();

//north
$xx = $x;
$yy = $y -1;
if ($yy >=0) {
$rgb = imagecolorat($this->sourceImage, $xx, $yy);
if ($rgb == 0xFFFFFF) {
$neighbors[] = $labels[$yy][$xx];
}
}


//west
$xx = $x-1;
$yy = $y;
if ($xx >=0) {
$rgb = imagecolorat($this->sourceImage, $xx, $yy);
if ($rgb == 0xFFFFFF) {
$neighbors[] = $labels[$yy][$xx];
}
}

//north-west
$xx = $x-1;
$yy = $y-1;
if ($xx >=0 && $yy >=0) {
$rgb = imagecolorat($this->sourceImage, $xx, $yy);
if ($rgb == 0xFFFFFF) {
$neighbors[] = $labels[$yy][$xx];
}
}

//north-east
$xx = $x+1;
$yy = $y-1;
if ($xx <$this->img_width && $yy >=0) {
$rgb = imagecolorat($this->sourceImage, $xx, $yy);
if ($rgb == 0xFFFFFF) {
$neighbors[] = $labels[$yy][$xx];
}
}

$neighbors = array_unique($neighbors);


if (empty($neighbors)) {
//$linked[$next_label] = array();
$linked[$next_label] = array($next_label);
$labels[$y][$x] = $next_label;
$next_label ++;
} else {
$labels[$y][$x] = min($neighbors);

foreach($neighbors as $v) {
$linked[$v] = array_unique(array_merge($linked[$v], $neighbors));
}
#$linked[$labels[$y][$x]] = array_unique(array_merge($linked[$v], $neighbors));
}


}
}


$distinct_labels = array();
for ($y = 0; $y <$this->img_height; $y++) {
for ($x = 0; $x <$this->img_width; $x++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
if ($rgb == 0xFFFFFF) {
//這裡不能直接用min(), 需要遞歸下去,找到最小值。
$l = $labels[$y][$x] = $this->findMin($linked, $labels[$y][$x] );

if (isset($distinct_labels[$l]))
$distinct_labels[$l]++;
else
$distinct_labels[$l] = 0;
}
}
}


arsort($distinct_labels, SORT_NUMERIC );
//print_r($distinct_labels);
/**
Array
(
[0] => 1242
[9] => 302
[7] => 233
[1] => 11
[13] => 5
[2] => 5
)
**/


//$available_labels = array_flip(array_keys(array_slice($distinct_labels, 0, 4, TRUE)));

//需要一個阈值, 去掉比較少的label.

if (count($distinct_labels) ==1) return;

$available_labels = array();
//去掉一個最大的。
$i = 0;
foreach($distinct_labels as $l=>$______) {

if ($i++ ==0 ) continue;
$available_labels[] = $l;
}




$available_labels = array_flip($available_labels);
//print_r($available_labels);die();
for ($y = 0; $y <$this->img_height; $y++) {
for ($x = 0; $x <$this->img_width; $x++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
if ($rgb != 0xFFFFFF) continue;

if (isset($available_labels[ $labels[$y][$x] ]) ) {
imagesetpixel($this->sourceImage, $x, $y, $this->closed_color);
} else {
imagesetpixel($this->sourceImage, $x, $y, 0xFFFFFF);
}
}
}
}


private function segment() {
print __FUNCTION__.PHP_EOL;
foreach($this->four_colors as $_k=>$_v) {
$begin_x = 0;
$end_x = 0;
$found_start = $found_end = false;
for ($x = 0; $x <$this->img_width; $x++) {
$no_blue_in_one_column = 0;
for ($y = 0; $y <$this->img_height; $y++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
if ($rgb == $_v) {
$no_blue_in_one_column ++;
}

}

if (!$found_start) {
if ($no_blue_in_one_column >0) {
$found_start = true;
$start_x = $x;
}
} else {
if (!$found_end && $no_blue_in_one_column == 0) {
$found_end = true;
$end_x = $x;
}
}

}

if (!$found_start || !$found_end) die("why can't find the bigest label?");

$end_x --;

$this->segment_lines[] = array(
"start_x"=>$start_x,
"end_x"=>$end_x,
"color"=>$_v,
);

$this->segment_lines2[] = $start_x;
$this->segment_lines2[] = $end_x;
}

//print_r($this->segment_lines);die();

sort($this->segment_lines2, SORT_NUMERIC);
}

private function projection() {
print __FUNCTION__.PHP_EOL;

$this->image_width = $this->img_width;
$this->image_height = $this->img_height;

$this->projection_count = array();
//closed region在投影進行判斷時,不做考慮。
for ($x = 0; $x <$this->image_width; $x++) {
$this->projection_count[$x] = 0;
for ($y = 0; $y <$this->image_height; $y++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
if ($rgb == 0xFFFFFF) continue;
//if (!in_array($rgb, $this->four_colors, true)) continue;
$this->projection_count[$x] ++;

}
}

}


private function projection_o() {
print __FUNCTION__.PHP_EOL;
$tmp_image= ImageCreateTrueColor($this->image_width, max($this->projection_count));
imagefill($tmp_image, 0 , 0 , 0xFFFFFF);
for($x=0; $x<$this->image_width; $x++) {
for($y=0;$y<$this->projection_count[$x];$y++) {
imagesetpixel($tmp_image, $x, $y, 0);
}
}


foreach($this->segment_lines2 as $k=>$xx) {
for($y=0;$y<$this->image_height; $y++) {
imagesetpixel($tmp_image, $xx, $y, 0xFF0000);
}
}


imagejpeg($tmp_image, $this->dst_file);
imagedestroy($tmp_image);
}

//這裡有問題。 如果是三個字母都在同一個label中呢? 每次切割之後,需要重新統計 $this->segment_lines.
private function relabel() {
print __FUNCTION__.PHP_EOL;
$index = 0;
while(true) {

$min = 1000000;
$x_min = -1;
$now = 0;
$start_x = $this->segment_lines[$index]['start_x'];
$end_x = $this->segment_lines[$index]['end_x'];
$color = $this->segment_lines[$index]['color'];
for($x=$start_x; $x<=$end_x - self::SLIDE_WINDOW_SIZE; $x++) {

for($xx = 0; $xx<self::SLIDE_WINDOW_SIZE; $xx++) {
$now += $this->projection_count[$x +$xx] ;
}

if ($now < $min) {
$min = $now;
$x_min = $x;
}
$now = 0;
}


assert($x_min != -1);

//分割不開也不要強分啊親。

$middle = intval($x_min + self::SLIDE_WINDOW_SIZE / 2);


#$color = $this->old_four_colors[$index];

for($x=$middle; $x<=$end_x; $x++) {
for($y=0; $y <$this->img_height; $y++) {
$rgb = imagecolorat($this->sourceImage, $x, $y);
if ($rgb != $color) continue;
imagesetpixel($this->sourceImage, $x, $y, $this->old_four_colors[$this->labels_count]);

}
}

$this->segment_lines[$index] = array(
"start_x"=>$start_x,
"end_x"=>$middle - 1,
"color"=>$color,
);

array_push($this->segment_lines, array(
"start_x"=>$middle,
"end_x"=>$end_x,
"color"=>$this->old_four_colors[ count($this->segment_lines) ],
));

array_push($this->segment_lines2, $middle);
array_push($this->segment_lines2, $middle-1);

sort($this->segment_lines2, SORT_NUMERIC);

$this->labels_count++;


if ($this->labels_count == self::LABEL_4_NO) break;

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved