CNN(卷积神经网络)算法一般应用在图像识别领域,如对数字字母的识别、区分猫狗等。卷积神经网络运算的第一步即使对输入图像进行边缘提
取。这篇文章用来讲解如何对图像的边缘进行提取。
算法思维跨越语言,这里用PHP语言来进行算法的讲解,实际开发中,非常不建议使用PHP来进行多次卷积运算,效率堪忧。
基础不清晰的请阅读本文代码下面的CNN基础,转自 CSDN博主ice_actor 写的一篇文章《吴恩达deeplearning之CNN—卷积神经网络入门》
在这里,将边缘提取用下面两张动态图片加以表示,接下来的算法机理便是基于这两张图片


<? php
/**
* 基于卷积神经网络算法的图像识别
* Bill
* 2018年9月7日 08点46分
*/
ini_set('memory_limit', '-1');
set_time_limit(0);
header('content-type: text/html; charset=utf-8;');
// $imagePath = './ehuixue/1.jpg';
// $imagePath = './img/1.jpg';
// $imagePath = './img/crh.jpg';
$imagePath = './img/train.jpg';
$array = getimagesize($imagePath);
print_r($array);
echo '<br/>';
echo '<h2>【图像初始样式 - 60%】</h2>';
echo '<img width="60%" src="'.$imagePath.
'"/>';
echo '<br/>';
echo '<br/>';
echo '<br/>';
$res = imagecreatefromjpeg($imagePath);
$size = getimagesize($imagePath);
$maxX = $size[0];
$maxY = $size[1];
// // echo "<pre>";
// // echo "<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">";
// // for ($i = 0; $i < $size[1]; ++$i) { // 行
// // echo "<tr>";
// // for ($j = 0; $j < $size[0]; ++$j) { // 列
// // $rgb = imagecolorat($res, $j, $i);
// // $rgbarray = imagecolorsforindex($res, $rgb);
// // echo "<td>";
// // echo $rgbarray['red'].',<br/>'.$rgbarray['green'].',<br/>'.$rgbarray['blue'];
// // echo "</td>";
// // }
// // echo "<tr>";
// // }
// // echo "</table>";
// // echo "</pre>";
// // echo "<br/>";
$input = array();
$emmm = imagecreatetruecolor($size[0], $size[1]);
for ($i = 0; $i < $size[0]; ++$i) { // x
for ($j = 0; $j < $size[1]; ++$j) { // y
$rgb = imagecolorat($res, $i, $j);
$rgbarray = imagecolorsforindex($res, $rgb);
$rgb = (int)(($rgbarray['red'] + $rgbarray['green'] / 3 + $rgbarray['blue']) / 12);
if ($rgb > 20) {
$color = imagecolorallocate($emmm, 255, 255, 255);
$input[$j][$i] = 255;
} else {
$color = imagecolorallocate($emmm, 0, 0, 0);
$input[$j][$i] = 0;
}
// $color = imagecolorallocate( $emmm, $rgb, $rgb, $rgb);
// $color = imagecolorallocate ( $emmm , 255 , 0 , 0 );// 设置颜色 - ps里的选择画笔颜色
imagesetpixel($emmm, $i, $j, $color);
}
}
date_default_timezone_set('PRC');
$now = time();
echo '<h2>【灰度化 - 60%】</h2>';
ImagePNG($emmm, './img/'.$now.
'.png');
// imagepng($emmm);
imagedestroy($emmm); // 销毁图片,释放内存
echo '<img width="60%" src="./img/'.$now.
'.png"/>';
echo '<br/>';
// $red = imagecolorallocate ( $image , 255 , 0 , 0 );// 设置颜色 - ps里的选择画笔颜色
// for($i=0; $i<300; ++$i){
// imagesetpixel ( $emmm , 100 , $i , $red );
// }
// header('Content-Type:image/jpg');
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// 二值化// 二值化// 二值化// 二值化// 二值化// 二值化// 二值化//
// 二值化// 二值化// 二值化// 二值化// 二值化// 二值化// 二值化//
// date_default_timezone_set('PRC');
// $now = time();
// ImagePNG($emmm,'./img/'.$now.'.png');
// // imagepng($emmm);
// imagedestroy($emmm);// 销毁图片,释放内存
// echo '<img src="./img/'.$now.'.png"/>';
// echo '<br/>';
// foreach($input as $key => $value){ // 先固定行,即y坐标,$j是y
// foreach($value as $inner => $x){
// if($x < 100){
// echo '1';
// }else{
// echo '0';
// }
// }
// echo '<br/>';
// }
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// 二值化// 二值化// 二值化// 二值化// 二值化// 二值化// 二值化//
// 二值化// 二值化// 二值化// 二值化// 二值化// 二值化// 二值化//
// print_r($input);
/**INPUT padding 处理 */
// 暂时不需要
// $input = $temp;
// print_r($input);
// exit;
// for ( $i = 0; $i < $x; ++$i ) { // 列
// for ( $j = 0; $j < $y; ++$j ) { // 行
// if ($input[$i][$j] < 80) {
// echo "1";
// }else{
// echo "0";
// }
// }
// echo '<br/>';
// }
$output = array(); // 卷积计算后输出
// 卷积计算
echo '<h2>【水平卷积过滤】</h2>';
/**
X过滤,算子:
1 0 -1
1 0 -1
1 0 -1
*/
$wx = array(
0 => array(1, 0, -1),
1 => array(1, 0, -1),
2 => array(1, 0, -1),
);
$wx = array(
0 => array(1, -1, 1),
1 => array(1, -1, 0),
2 => array(1, -1, -1),
);
for ($i = 0; $i < ($maxY - 2); ++$i) { // 固定行
for ($j = 0; $j < ($maxX - 2); ++$j) { // 遍历列
$output[$i + 1][$j + 1] = 0; // 赋初始值
$temp = array(
0 => array($input[$i + 0][$j + 0], $input[$i + 1][$j + 0], $input[$i + 2][$j + 0]),
1 => array($input[$i + 0][$j + 1], $input[$i + 1][$j + 1], $input[$i + 2][$j + 1]),
2 => array($input[$i + 0][$j + 2], $input[$i + 1][$j + 2], $input[$i + 2][$j + 2]),
);
// 卷积计算
for ($m = 0; $m < 3; ++$m) {
for ($n = 0; $n < 3; ++$n) {
$output[$i + 1][$j + 1] += $temp[$m][$n] * $wx[$m][$n];
}
}
}
}
echo "<br/>";
echo "<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">";
for ($i = 0; $i < ($maxY - 2); ++$i) { // 固定行
echo "<tr>";
for ($j = 0; $j < ($maxX - 2); ++$j) { // 遍历列
echo "<td>";
echo reluActive($output[$i + 1][$j + 1]);
echo "</td>";
}
echo "</tr>";
}
echo "</table>";
echo "<br/>";
$emmm = imagecreatetruecolor($maxX - 2, $maxY - 2);
for ($i = 0; $i < ($maxY - 2); ++$i) { // 固定行
echo "<tr>";
for ($j = 0; $j < ($maxX - 2); ++$j) { // 遍历列
$rgb = $output[$i + 1][$j + 1];
$color = imagecolorallocate($emmm, $rgb, $rgb, $rgb);
imagesetpixel($emmm, $j, $i, $color);
}
}
date_default_timezone_set('PRC');
$now = time();
ImagePNG($emmm, './img/filtered'.$now.
'.png');
// imagepng($emmm);
imagedestroy($emmm); // 销毁图片,释放内存
echo '<img width="60%" src="./img/filtered'.$now.
'.png"/>';
echo '<br/>';
$output1 = array(); // 卷积计算后输出
echo '<h2>【垂直卷积过滤】</h2>';
/**
Y过滤,算子:
1 1 1
0 0 0
-1 -1 -1
*/
$wy = array(
0 => array(1, 1, 1),
1 => array(0, 0, 0),
2 => array(-1, -1, -1),
);
for ($i = 0; $i < ($maxY - 2); ++$i) { // 固定行
for ($j = 0; $j < ($maxX - 2); ++$j) { // 遍历列
$output1[$i + 1][$j + 1] = 0; // 赋初始值
$temp = array(
0 => array($input[$i + 0][$j + 0], $input[$i + 1][$j + 0], $input[$i + 2][$j + 0]),
1 => array($input[$i + 0][$j + 1], $input[$i + 1][$j + 1], $input[$i + 2][$j + 1]),
2 => array($input[$i + 0][$j + 2], $input[$i + 1][$j + 2], $input[$i + 2][$j + 2]),
);
// 卷积计算
for ($m = 0; $m < 3; ++$m) {
for ($n = 0; $n < 3; ++$n) {
$output1[$i + 1][$j + 1] += $temp[$m][$n] * $wy[$m][$n];
}
}
}
}
echo "<br/>";
echo "<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">";
for ($i = 0; $i < ($maxY - 2); ++$i) { // 固定行
echo "<tr>";
for ($j = 0; $j < ($maxX - 2); ++$j) { // 遍历列
echo "<td>";
echo reluActive($output1[$i + 1][$j + 1]);
echo "</td>";
}
echo "</tr>";
}
echo "</table>";
echo "<br/>";
$emmm = imagecreatetruecolor($maxX - 2, $maxY - 2);
for ($i = 0; $i < ($maxY - 2); ++$i) { // 固定行
echo "<tr>";
for ($j = 0; $j < ($maxX - 2); ++$j) { // 遍历列
$rgb = $output1[$i + 1][$j + 1];
$color = imagecolorallocate($emmm, $rgb, $rgb, $rgb);
imagesetpixel($emmm, $j, $i, $color);
}
}
date_default_timezone_set('PRC');
$now = time();
ImagePNG($emmm, './img/filtered1'.$now.
'.png');
// imagepng($emmm);
imagedestroy($emmm); // 销毁图片,释放内存
echo '<img width="60%" src="./img/filtered1'.$now.
'.png"/>';
echo '<br/>';
$final = array();
echo '<h2>【X+Y卷积结果】</h2>';
// XY合并
for ($i = 0; $i < ($maxY - 2); ++$i) { // 固定行
for ($j = 0; $j < ($maxX - 2); ++$j) { // 遍历列
$final[$i][$j] = ($output[$i + 1][$j + 1]) ? ($output[$i + 1][$j + 1]) : ($output1[$i + 1][$j + 1]);
}
}
echo "<br/>";
echo "<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">";
for ($i = 0; $i < ($maxY - 2); ++$i) { // 固定行
echo "<tr>";
for ($j = 0; $j < ($maxX - 2); ++$j) { // 遍历列
echo "<td>";
echo reluActive($final[$i][$j]);
echo "</td>";
}
echo "</tr>";
}
echo "</table>";
echo "<br/>";
$emmm = imagecreatetruecolor($maxX - 2, $maxY - 2);
for ($i = 0; $i < ($maxY - 2); ++$i) { // 固定行
echo "<tr>";
for ($j = 0; $j < ($maxX - 2); ++$j) { // 遍历列
$rgb = $final[$i][$j];
$color = imagecolorallocate($emmm, $rgb, $rgb, $rgb);
imagesetpixel($emmm, $j, $i, $color);
}
}
date_default_timezone_set('PRC');
$now = time();
ImagePNG($emmm, './img/final'.$now.
'.png');
// imagepng($emmm);
imagedestroy($emmm); // 销毁图片,释放内存
echo '<img width="60%" src="./img/final'.$now.
'.png"/>';
echo '<br/>';
function reluActive($x) {
return max(0, $x);
}- 这里附上
train.jpg

- 灰度化处理后

- 水平卷积算法处理

- 垂直卷积算法处理

- 水平 + 垂直 叠加后 处理

至此,train.jpg的边缘通过卷积计算提取了出来
提供云存储服务