PHP读取图片数据原理与实现

来源:互联网 发布:九搜网络用户中心 编辑:程序博客网 时间:2024/06/01 22:05
好久没有写文章了,手也开始痒痒了

这次为大家带来的是一个关于PHP提取图片数据的内容

这里没有什么新技术,只是为了让大家了解PHP也可以处理图片以及处理的原理和方式

在此实现一个简单的DEMO,读取图片中指定位置的数据‘特定字母+数字’(本例图片来源于cacti监控流量图片)


以下两步分开单进行

I 先来取模操作,实现步骤:
1.定位图片需要识别区域,从图片中取出此部分
2.将此部分的字模提取出来,记录到字模文件中,供以后匹配使用(为了得到完整的字模,所以需要多张图片进行测试)


II进行图片文字提取,实现步骤:

1.定位图片需要识别区域,从图片中取出此部分

2.将此部分的字模提取出来,与已经保存好的字模文件中数据对比,找出此字模对应的数据即可


这两步分开说,个人觉得是很有必要的,虽然他们有很多相似之处,但毕竟两者是两个不同的过程

刚洗个澡想了一下,还是觉得先介绍第二部分,然后在介绍第一部分,这样大家可能会有兴趣点,先看到结果,勾起你们的欲望,哈哈哈…


正式进入主题:

先将需要操作的类放出来,点击下面右边箭头可查看类文件
PHP code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
<?php
/***
 * @author: Buty(孟婆)
 
 */
 
class picWords {
    private $width;
    private $height;
    private $zimo_file 'piczimo.php'//需要生成的字模文件
    private $zimo_info '';
    private $continued//高峰流量持续的时间
    private $warnning_data//流量报警峰值
    private $hourstep//一小时在时间轴上的长度
    function __construct() {
        if(!extension_loaded('gd')) { //需要gd扩展的支持
            exit('GD extension is supported,please load GD extension and go on.');
        }
        if(file_exists('config.php')) {
            require 'config.php';
            $this->continued = $continued;
            $this->warnning_data = $warnning_data;
            $this->hourstep = $hourstep;
        }
         
    }
 
/*****************************************自行创建字模图片与字模数组文件********************************/   
    function readPicDot($picfile) {
        $res = imagecreatefrompng($picfile);
        $size getimagesize($picfile);
        $this->width = $size[0];
        $this->height = $size[1];
 
        $data array();
         
        for($j = 0; $j $this->height; ++$j) {
            /*
             * 取需要的数据段 
             * 262,273 day.png
             */
             
            if($j > 262 && $j < 273) {   
                for($i=0; $i $this->width; ++$i) {
                    if($i > 420) {
                        $rgb = imagecolorat($res,$i,$j);
                        $rgbarray = imagecolorsforindex($res$rgb);
                        if($rgbarray['red'] < 145 && $rgbarray['green'] < 145 & $rgbarray['blue'] < 145) {
                            $data[$i][$j]=1;
                        else {
                            $data[$i][$j]=0;
                        }
                    }
                }
                 
            }
        }
         
        return $data;
    }
    function readMaxOutDot($picfile) {
        $res = imagecreatefrompng($picfile);
        $size getimagesize($picfile);
        $this->width = $size[0];
        $this->height = $size[1];
 
        $data array();
         
        for($j = 0; $j $this->height; ++$j) {
            /*
             * 取需要的数据段 
             * 262,273 day.png
             */
             
            if($j > 262 && $j < 273) {   
                for($i=0; $i $this->width; ++$i) {
                    if($i < 180 && $i > 90) {
                        $rgb = imagecolorat($res,$i,$j);
                        $rgbarray = imagecolorsforindex($res$rgb);
                        if($rgbarray['red'] < 145 && $rgbarray['green'] < 145 & $rgbarray['blue'] < 145) {
                            $data[$i][$j]=1;
                        else {
                            $data[$i][$j]=0;
                        }
                    }
                }
                 
            }
        }
         
        return $data;
    }   
     
     
    function readHourDot($picfile) {
        $res = imagecreatefrompng($picfile);
        $size getimagesize($picfile);
        $this->width = $size[0];
        $this->height = $size[1];
 
        $data array();
         
        for($j = 0; $j $this->height; ++$j) {
            /*
             * 取需要的数据段 
             * popup_module_view_hour.png
             * 25, 245 # 35, 480
             
             */
             
            if($j > 30 && $j < 242) {   
                for($i=0; $i $this->width; ++$i) {
                    if($i >66 && $i < 486) {
                        $rgb = imagecolorat($res,$i,$j);
                        $rgbarray = imagecolorsforindex($res$rgb);
                        if(($rgbarray['red'] < 50 && $rgbarray['green'] > 180 && $rgbarray['blue'] < 50) || ($rgbarray['red'] < 145 && $rgbarray['green'] < 145 & $rgbarray['blue'] < 145)) {
                            $data[$i][$j]=1;
                        else {
                            $data[$i][$j]=0;
                        }
                    }
                }
                 
            }
        }
         
        return $data;
    }
     
    function cutData($data) {
        $zimo $tmp array();
        $num $len = 0;
        $count_start = false;
        foreach($data as $k => $v) {
            if(in_array(1, $v)) {
                 
                $zimo[$num][] = $v;
                $count_start = true;
                $len++;
                if($len >= 6) {  //解决字体连在一起
                    $len = 0;
                    $num++; //字数加1
                }
                 
            else {
                $len = 0;
                $count_start = false;
            }
            if(!$count_start) {
                $num++;
            }
        }
        //var_dump(array_keys($zimo));
         
        //对于字母T的修复
        $res $this->createZimoArray($zimo);
        //$this->debugPic($zimo[35]);
        //die();
        //打印完整字模点阵
        /*
        foreach($zimo as $k => $v) {
 
            if($k == 35) {
                echo '<hr />';
                $this->debugPic($v);
            }
        }
        */
         
        //var_dump($res);
        end($res);//移动数据指针
        $last_two_data = prev($res);
         
        if(!strcmp($last_two_data'0100000000')) { //说明切割T时存在问题
            $last_three_data = prev($res);
            $last_three_data_real $last_three_data $last_two_data//补充到T字母中
            foreach($res as $k => $v) {
                if(!strcmp($v$last_three_data)) {
                    $res[$k] = $last_three_data_real;
                }
            }
             
        }
        return $res;
    }
     
    //构造字模数组
    function createZimoArray($data) {
        $str array();
        foreach($data as $k => $v) {
            $str[$k] = '';
            foreach($v as $ks => $vs) {
                $str[$k] .= implode(''$vs);
            }
        }
        return $str;
    }
     
    //将数据字模读入文件中
    function storeZimo($data) {
        $str $this->createZimoArray($data);
        $picwords = APP_CACHE_PATH.'picwords.php';
        swritefile($picwords"<?php\r\nreturn ".var_export($str, true)."\r\n?>");
 
    }
    //匹配字模数据
    function matchZimo($str_arr) {
        $need_str '';
        $picwords $this->zimo_file;
        if(empty($this->zimo_info)) {
            $this->zimo_info = include_once($picwords);
        }
        foreach($str_arr as $k => $v) {
            foreach($this->zimo_info as $ks => $vs) {
                similar_text($v$vs$tmp);
                if($tmp > 99)
                    $need_str .= $ks;
            }
        }
        return $need_str;
    }
     
    function debugPic($data) {
            echo '<div style="width:5850px">';
            foreach($data as $k => $v) {
                echo '<div style="float:left">';
                foreach($v as $ks => $vs) {
                    echo $vs."<br />";
                }
                echo '</div>';
            }
            echo '</div>';
    }
    function handleHourData($data) {
        $data_info array();
        foreach($data as $k => $v) {
            $get = true;
            $data_info[$k] = 0;
            foreach($v as $ks => $vs) {
                if($vs == 1 && $get) {
                    $get = false;
                }
                if(!$get) {
                    $data_info[$k]++;
                     
                else {
                    unset($data[$k][$ks]);
                }
            }
        }
        return $data_info;
    }
 
/************************************取数据的方法*******************************/
    //总流量
    function getPicWords($file) {
        $need_str '';
        //读取图片点阵信息
        $data $this->readPicDot($file);
         
        //处理切割到的数据,并写入数组
        $data $this->cutData($data);
 
        //匹配字模数据
        $need_str $this->matchZimo($data);
        return $need_str;
    }
    //得到最大流量速度
    function getMaxSpeed($file) {
        $need_str '';
         
        //读取图片点阵信息
        $data $this->readMaxOutDot($file);
        //处理切割到的数据,并写入数组
        $data $this->cutData($data);
        //匹配字模数据
        $need_str $this->matchZimo($data);
        return $need_str;
    }
    //分析小时图中的流量峰值
    function parseFlow($file$info) {
        //得到最大流量速度
        $maxflow floatval($this->getMaxSpeed($file));
 
        //读取图片点阵信息
        $data $this->readHourDot($file);
        //数据抽象形变
        $data_info $this->handleHourData($data);
         
        $max = max($data_info);
         
        $radio = (float) ($maxflow $max); //流量计算比列
         
        $timeradio ceil($this->hourstep / 60);//每分钟格数
         
        $continued_time $this->continued * $timeradio;//持续时间用点阵长度量化
         
        $count = 0;
        foreach($data_info as $v) {
            if($v $radio $this->warnning_data) {
                $count++;
                if($count >= $continued_time) {
                    echo "ServerID: $info[sid] IP: $info[ip] flow over: ".$this->warnning_data.'<br />'//发邮件
                    break;
                }
            else {
                $count = 0;
            }
        }
 
    }
     
}
?>


一.文字提取功能介绍

需要操作的图片,下面红字部分是我们需要取出的文字

经过代码处理后得到如下图片
PHP code
?
1
2
3
4
5
<?php
$picWord new picWords();
$picfile 'popup_module_view.png';//图片路径
$data $picWord->readPicDot($picfile);//读取图片点阵信息
?>



此图片由一组0、1表示,相信大家都看的出来这图里面的字符串吧


到此我们已经缩小了我们操作对象的范围,马上问题也来了,我们如何可以得图片中的字符个数及字符

这个问题也是最难的,到此我们就开始切割了

经过代码处理得到如下图片:
PHP code
?
1
2
3
<?php
$data $picWord->cutData($data);//处理切割到的数据,并写入数组
?>



每一个块都对应一个字符(此时还不是真正的字符,还只是未知数据,等待咱们去转换)

细心的朋友应该看出来了,倒数据第二、三块,其实是表示的一个T,后续代码中对此有单独的处理

在此解释一下,因为我是按每个字符6个像素来宽图和10个像素高度来计算的,或许有同学来问了,那你怎么就一定要用这样两个数字来计算呢?我想说,这些是在对此图片里面的文字观察来的,5,7都不行,所以就选了6作宽度,高度很容易看出来10
PHP code
?
1
2
3
<?php
$need_str$picWord->matchZimo($data);//匹配字模数据
?>


然后在将保存这些字符串的数组转化为’10101010…’的字符串,以及与字模文件(这里我们先用,后面我们在介绍它)匹配,然后得到我们要的数据



二.生成字模

生成字模的过程跟上面的是一样的,只是在最后需要我们人工去识别、记录保存字符的数组中的字符串与对应的字符,此步聚一定要在上面之前完成,不然上面没有可以用来匹配的字模文件。

或许同学们要说,这还是得人工去识别,不是智能的。但没有现成的字模文件,所以我们必须手动去生成。要是那位同学对于字体字模有研究,一眼可以看出来图片中的文字是用哪种字模同时有此字模文件,那到是可以不用咱们人工生成,直接借来一用即可


好了今天这篇文章就到这里了,取到文件中的固定文字

一个DEMO下载地址,完整的代码,有兴趣的同学可以下载交流一下,点击下载DEMO
解压文件后运行pick_pic_data.php即可,图片文件也可以在此文件重随意指定

下次我们在介绍如何根据波形来检测超过某个固定值的情况,从而做出回应
0 0
原创粉丝点击