1
+ const cv = require ( 'sharp' ) ;
2
+ const fakeOpenCV = require ( "../../lib/fakeOpenCV" ) ;
3
+ const fs = require ( "fs" ) ;
4
+
5
+ const main = async ( file ) => {
6
+ var timeBegin = Date . now ( ) ;
7
+ var image = [ ] ;
8
+ image [ 0 ] = cv ( file ) ;
9
+ var meta = await image [ 0 ] . metadata ( ) ;
10
+ //console.log(meta);
11
+ var size = { width : meta . width , height : meta . height } ;
12
+
13
+ //裁边
14
+ image [ 1 ] = image [ 0 ] . clone ( ) . extract ( { left : 1 , top : 1 , width : meta . width - 2 , height : meta . height - 2 } )
15
+ size . width -= 2 ;
16
+ size . height -= 2 ;
17
+ //await showImage(image[1], '裁边');
18
+
19
+ //灰度
20
+ image [ 2 ] = image [ 1 ] . clone ( ) . greyscale ( ) ;
21
+ //debugFlag && (await showImage(image[2], '灰度'));
22
+
23
+ //二值化
24
+ image [ 3 ] = image [ 2 ] . clone ( ) . threshold ( 255 ) . toColourspace ( 'b-w' ) ;
25
+ debugFlag && ( await showImage ( image [ 3 ] , '二值化' ) ) ;
26
+
27
+ //空穴填充
28
+ image [ 5 ] = image [ 3 ] . clone ( ) . linear ( - 1 , 255 ) . convolve ( {
29
+ width : 3 ,
30
+ height : 3 ,
31
+ kernel : [
32
+ 0 , 1 / 4 , 0 ,
33
+ 1 / 4 , 1 , 1 / 4 ,
34
+ 0 , 1 / 4 , 0
35
+ ] ,
36
+ } )
37
+ image [ 5 ] = await superDeepCopySharp ( image [ 5 ] ) ;
38
+ image [ 5 ] = image [ 5 ] . threshold ( 128 ) . toColourspace ( 'b-w' ) . linear ( - 1 , 255 ) ;
39
+ debugFlag && ( await showImage ( image [ 5 ] , '空穴填充' ) ) ;
40
+
41
+ //形态学膨胀
42
+ var buffer = await image [ 5 ] . clone ( ) . raw ( ) . toBuffer ( ) ;
43
+ var element = fakeOpenCV . math . ones ( 3 , 3 ) ;
44
+ var imageMath = fakeOpenCV . transformMath ( { buffer, size} )
45
+ var res = fakeOpenCV . dilate ( imageMath , element ) ;
46
+ var resBuffer = fakeOpenCV . transformBuffer ( res ) ;
47
+ image [ 4 ] = await cv ( resBuffer . buffer , { raw : { width : resBuffer . size . width , height :resBuffer . size . height , channels : 1 } } ) ;
48
+ debugFlag && ( await showImage ( image [ 4 ] , '膨胀' ) ) ;
49
+
50
+ //连通域
51
+ var res2 = fakeOpenCV . connectedComponents ( fakeOpenCV . inverse ( res ) ) ;
52
+
53
+ //分割及演示
54
+ var points = [ ] ;
55
+ var index2 = 0 ;
56
+ var marks = [ ] ;
57
+ res2 . marks . forEach ( ( value , index ) => {
58
+ var pos = value . position ;
59
+ function setPoints ( index2 , pos ) {
60
+ points [ index2 ] = [
61
+ [ pos . y , pos . x ] ,
62
+ [ pos . y + pos . h - 1 , pos . x ] ,
63
+ [ pos . y + pos . h - 1 , pos . x + pos . w - 1 ] ,
64
+ [ pos . y , pos . x + pos . w - 1 ] ,
65
+ [ pos . y , pos . x ]
66
+ ] ;
67
+ marks [ index2 ] = pos ;
68
+ marks [ index2 ] . area = pos . w * pos . h ;
69
+ marks [ index2 ] . cX = Math . floor ( pos . x + pos . w / 2 ) ;
70
+ marks [ index2 ] . cY = Math . floor ( pos . y + pos . h / 2 ) ;
71
+ }
72
+ //针对超宽的目标块二次对半分割
73
+ if ( pos . w > pos . h * 1.5 ) {
74
+ pos = { x : pos . x , y : pos . y , w : Math . floor ( pos . w / 2 ) , h : pos . h } ;
75
+ setPoints ( index2 ++ , pos ) ;
76
+ pos = { x : pos . x + pos . w , y : pos . y , w : pos . w , h : pos . h } ;
77
+ setPoints ( index2 ++ , pos ) ;
78
+ } else {
79
+ setPoints ( index2 ++ , pos ) ;
80
+ }
81
+ } ) ;
82
+ //points = [[[0, 0], [0, 20], [10, 20], [10, 0], [0, 0]]]
83
+ var res3 = fakeOpenCV . rectangle ( res , points ) ;
84
+ var resBuffer = fakeOpenCV . transformBuffer ( res3 ) ;
85
+ image [ 5 ] = cv ( resBuffer . buffer , { raw : { width : resBuffer . size . width , height :resBuffer . size . height , channels : 1 } } ) ;
86
+ //debugFlag && (await showImage(image[5], '分割'));
87
+ //console.log(res2.marks);
88
+
89
+ //取出字符块
90
+ var imageList = [ ] ;
91
+ marks . sort ( ( a , b ) => b . area - a . area ) ;
92
+ marks . splice ( 4 ) ;
93
+ marks . sort ( ( a , b ) => a . cX - b . cX ) ;
94
+ var w = 45 , h = 50 ;
95
+ for ( let i = 0 ; i < marks . length ; i ++ ) {
96
+ let imageExt = image [ 4 ]
97
+ . clone ( )
98
+ . extract ( { left : marks [ i ] . x , top : marks [ i ] . y , width : marks [ i ] . w , height : marks [ i ] . h } )
99
+ . extend ( {
100
+ top : Math . floor ( ( h - marks [ i ] . h ) / 2 ) ,
101
+ bottom : h - Math . floor ( ( h - marks [ i ] . h ) / 2 ) - marks [ i ] . h ,
102
+ left : Math . floor ( ( w - marks [ i ] . w ) / 2 ) ,
103
+ right : w - Math . floor ( ( w - marks [ i ] . w ) / 2 ) - marks [ i ] . w ,
104
+ background : "white"
105
+ } ) ;
106
+ let imageJPEG = await imageExt . jpeg ( {
107
+ quality : 100 ,
108
+ chromaSubsampling : '4:4:4'
109
+ } ) . toBuffer ( ) ;
110
+ imageList [ i ] = imageJPEG ;
111
+ debugFlag && ( await showImage ( imageExt , i ) ) ;
112
+ }
113
+ return { result : imageList , time : Date . now ( ) - timeBegin , marks } ;
114
+ }
115
+
116
+ const showImage = async ( image , name ) => {
117
+ var scale = 10 ;
118
+ var imageCopy = await superDeepCopySharp ( image ) ;
119
+ var meta = await imageCopy . metadata ( ) ;
120
+ imageCopy
121
+ . clone ( )
122
+ . resize ( {
123
+ width : meta . width * scale ,
124
+ kernel : cv . kernel . nearest
125
+ } )
126
+ . jpeg ( {
127
+ quality : 100 ,
128
+ chromaSubsampling : '4:4:4'
129
+ } )
130
+ . toBuffer ( )
131
+ . then ( data => {
132
+ var tmp = require ( 'tmp' ) ;
133
+ var tmpobj = tmp . dirSync ( { prefix : 'sharp_' } ) ;
134
+ debugFlag && console . log ( 'Dir: ' , tmpobj . name ) ;
135
+ var join = require ( "path" ) . join ;
136
+ var exec = require ( 'child_process' ) . exec ;
137
+ var tempPNGPath = join ( tmpobj . name , `${ name } .jpg` ) ;
138
+ fs . writeFileSync ( tempPNGPath , data ) ;
139
+ exec ( `explorer.exe "${ tempPNGPath } "` ) ;
140
+ } )
141
+ . catch ( err => { console . error ( err ) } ) ;
142
+ }
143
+
144
+ const superDeepCopySharp = async ( image ) => {
145
+ var { data, info } = await image . raw ( ) . toBuffer ( { resolveWithObject : true } ) ;
146
+ var pixelArray = new Uint8ClampedArray ( data . buffer ) ;
147
+ var { width, height, channels } = info ;
148
+ return cv ( pixelArray , { raw : { width, height, channels } } ) ;
149
+ }
150
+
151
+ module . exports = main ;
152
+ var debugFlag = false ;
153
+
154
+
155
+ //debugFlag = true;
156
+ if ( debugFlag ) {
157
+ //let code = "TTKO";
158
+ //let code = "54JY";
159
+ //let code = "7RVO";
160
+ //let code = "R796";
161
+ //let code = "XP1R";
162
+ //let code = "XSVG";
163
+ //let code = "XQKA";
164
+ let code = "I8YO" ;
165
+ let file = fs . readFileSync ( `./examples/${ code } .gif` ) ;
166
+ main ( file )
167
+ . then ( res => console . log ( res ) )
168
+ . catch ( err => { console . error ( err ) } ) ;
169
+ } ;
0 commit comments