示例图片
思路:读取图片,二值化(阈值,这里用的是alpha),获取边界,分块,过滤小块(环形)
代码实现
1 <?php 2 ini_set ( ‘memory_limit‘, ‘999M‘ ); 3 $ImagePath = ‘./test.png‘; 4 $res = imageCreateFromAny($ImagePath); 5 $size = getimagesize($ImagePath); 6 7 $pictype = substr($ImagePath, strrpos($ImagePath, ‘.‘)); 8 9 //获取图片像素点,并alpha二值化生成数组,原始数据 10 $data = array(); 11 for($i=0; $i < $size[1]; ++$i) 12 { 13 for($j=0; $j < $size[0]; ++$j) 14 { 15 $rgb = imagecolorat($res,$j,$i); 16 $rgbarray = imagecolorsforindex($res, $rgb); 17 if($rgbarray[‘alpha‘] < 125) 18 { 19 $data[$i.‘_‘.$j]=1; 20 }else{ 21 $data[$i.‘_‘.$j]=0; 22 } 23 } 24 } 25 //消融掉内部点生成边界数组 26 $bordersArr = []; 27 foreach ($data as $now => $ttt) { 28 if ($ttt == 1) { 29 $tmpnow = explode(‘_‘, $now); 30 $s = $tmpnow[0]; 31 $t = $tmpnow[1]; 32 $nowlist = getlist($s, $t, 1); 33 $tmpbor = getborder($nowlist, $data); 34 if ($tmpbor) { 35 if (!in_array($now, $bordersArr)) { 36 $bordersArr[] = $now; 37 } 38 } 39 } 40 } 41 42 //路径数组,记录所有走过的点 43 $allarr = []; 44 45 //临时块数组,记录一个块内的所有数据 46 $tmparr = []; 47 48 //结果数组 49 $resdata = []; 50 51 //分块,获取结果 52 saolei($bordersArr, $data); 53 $fenkuaiArr = []; 54 foreach ($resdata as $pickey => $resinfo) { 55 $x_arr = []; 56 $y_arr = []; 57 foreach ($resinfo as $tmpval) { 58 $tmpvalArr = explode(‘_‘, $tmpval); 59 $y_arr[] = $tmpvalArr[0]; 60 $x_arr[] = $tmpvalArr[1]; 61 } 62 $min_x = min($x_arr); 63 $min_y = min($y_arr); 64 $max_x = max($x_arr); 65 $max_y = max($y_arr); 66 $fenkuaiArr[] = [$min_x,$min_y,$max_x,$max_y]; 67 } 68 69 //过滤掉小块 70 $bigkuai = []; 71 foreach ($fenkuaiArr as $kuailist) { 72 $bigflag = getbigkuai($kuailist, $fenkuaiArr); 73 if ($bigflag) { 74 $bigkuai[] = $kuailist; 75 } 76 } 77 78 //分块截图 79 if ($bigkuai) { 80 foreach ($bigkuai as $bigk => $bigli) { 81 $tmpimg = imageCreateFromAny($ImagePath); 82 $new_width = $bigli[2]-$bigli[0]; 83 $new_height = $bigli[3]-$bigli[1]; 84 $image_p = imagecreatetruecolor($new_width, $new_height); 85 imagecopyresampled($image_p, $tmpimg, 0, 0, $bigli[0], $bigli[1], $new_width, $new_height, $new_width, $new_height); 86 $savename = ‘./tmp‘.$bigk.$pictype; 87 // 输出 88 imagejpeg($image_p, $savename); 89 imagedestroy($image_p); 90 imagedestroy($tmpimg); 91 } 92 } 93 94 //核心方法,图片分块 95 function saolei($bordersArr, $data, $thefirst = [], $num = 0) 96 { 97 global $allarr; 98 global $tmparr; 99 global $resdata; 100 if (!$thefirst) { 101 if (!$tmparr) { 102 $tttarr = array_diff($bordersArr, $allarr); 103 if (!$tttarr) { 104 return; 105 } 106 $thefirst = [$tttarr[array_keys($tttarr)[0]]]; 107 $tmparr[] = $thefirst[0]; 108 } else { 109 $thefirst = [$tmparr[count($tmparr)-1]]; 110 } 111 } 112 $tttdata = []; 113 foreach ($thefirst as $thepoint) { 114 $allarr[] = $thepoint; 115 $tmpdir = explode(‘_‘, $thepoint); 116 $thes = $tmpdir[0]; 117 $thet = $tmpdir[1]; 118 119 $alllist = getlist($thes, $thet, 1); 120 $reslist = getnext($alllist, $data); 121 $choselist = array_diff($reslist, $allarr); 122 if ($choselist) { 123 foreach ($choselist as $theli) { 124 if (in_array($theli, $bordersArr)) { 125 $tmparr[] = $theli; 126 $allarr[] = $theli; 127 $tttdata[] = $theli; 128 } 129 } 130 } 131 } 132 if (!$tttdata) { 133 $resdata[] = $tmparr; 134 $tmparr = []; 135 //调到下一个块 136 saolei($bordersArr, $data); 137 } else { 138 saolei($bordersArr, $data, $tttdata, $num+1); 139 } 140 } 141 142 //获取临点数组(9宫格) 143 function getlist($a, $b, $num=1) 144 { 145 $widarr = range($a-$num, $a+$num); 146 $hiharr = range($b-$num, $b+$num); 147 $resArr = []; 148 foreach ($widarr as $wid) { 149 if ($wid >= 0) { 150 foreach ($hiharr as $hih) { 151 if ($hih >= 0) { 152 $resArr[] = $wid."_".$hih; 153 } 154 } 155 } 156 } 157 return $resArr; 158 } 159 160 //读取图片 161 function imageCreateFromAny($filepath) 162 { 163 $type = exif_imagetype($filepath); 164 $allowedTypes = array( 165 1, // [] gif 166 2, // [] jpg 167 3, // [] png 168 6 // [] bmp 169 ); 170 if (!in_array($type, $allowedTypes)) { 171 return false; 172 } 173 switch ($type) { 174 case 1 : 175 $im = imageCreateFromGif($filepath); 176 break; 177 case 2 : 178 $im = imageCreateFromJpeg($filepath); 179 break; 180 case 3 : 181 $im = imageCreateFromPng($filepath); 182 break; 183 case 6 : 184 $im = imageCreateFromBmp($filepath); 185 break; 186 } 187 return $im; 188 } 189 190 //边界判断 191 function getborder($list, $data) 192 { 193 $tmpborders = []; 194 foreach ($list as $thev) { 195 if ($data[$thev] == 1) { 196 $tmpborders[] = $thev; 197 } 198 } 199 if (count($tmpborders) < 9) { 200 return true; 201 } else { 202 return false; 203 } 204 } 205 206 //获取相邻的边界点 207 function getnext($list, $data) 208 { 209 $tmpborders = []; 210 foreach ($list as $thev) { 211 if ($data[$thev] == 1) { 212 $tmpborders[] = $thev; 213 } 214 } 215 if (count($tmpborders) > 1) { 216 return $tmpborders; 217 } else { 218 return []; 219 } 220 } 221 222 //判断是否是大块(如果是小块,会有在大块内部) 223 function getbigkuai($thelist, $alllist) 224 { 225 $flag = true; 226 foreach ($alllist as $nextlist) { 227 if ($thelist!=$nextlist) { 228 if ($thelist[0]>=$nextlist[0] && $thelist[1]>=$nextlist[1] && $thelist[2]<=$nextlist[2] && $thelist[3]<=$nextlist[3]) { 229 $flag = false; 230 } 231 } 232 } 233 return $flag; 234 }
这个实现目前只能处理一些简单的序列帧,复杂的耗时太长,效率不高
原文:https://www.cnblogs.com/jwcrxs/p/10446001.html