PHP实现 序列帧拆分

示例图片

 

思路:读取图片,二值化(阈值,这里用的是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 }

 

 

这个实现目前只能处理一些简单的序列帧,复杂的耗时太长,效率不高

 

posted on 2019-02-27 19:07  叫我超人先生  阅读(564)  评论(0编辑  收藏  举报

导航