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