想要将双目照片合成立体图实现三维重建,完全没有头绪。但是对三维理解是必须的。所以将以前在单片机上运行的 3D画图 程序移植到python上。效果如下:

没有用numpy、openGL等,只用了纯math库,这样移植起来很快,只需要将原来的C代码简单修改就可以了,但代价是效率很低,后面加上图片旋转后更为明显,速度急剧下降,功耗急剧上升,台式机带起来速度都不怎么样,更别说运行在JetsonTx2开发板上了。

理论上来说,只要实现了里面的画点函数和画线函数,就可以快速移植到包括 Micropython在内的python环境中了,我的好几块Mycropython板子不知扔哪去了,之前的编程环境也不好找了,屏幕还需要现插,就不实验了。

突然发现我还有块荔枝派的堪智K210开发板,上面刷了Micropython环境,等有空移植试试。

整个程序是在以前的 3D旋转立方体 的C代码上移植过来的,新增加了任意中文字符显示函数和图片显示函数,图片显示使用了opencv。

程序中,最核心的处理部分就是以下几点:

    gMAT=structure_3D()    			      #//构建单位矩阵
gMAT=Translate3D(gMAT,-(width/2),-(height/2),0); #//平移变换矩阵
gMAT=Scale_3D(gMAT,size,size,size); #//比例变换矩阵
gMAT=Rotate_3D(gMAT,ax,ay,az); #//旋转变换矩阵 Point1=vector_matrix_MULTIPLY(Point0,gMAT) #坐标点矩阵变换,Point0即为当前点的三维坐标
PointDis=PerProject(Point1,0,0) #三维转二维计算

 然后按照上面的顺序,将每个点带入Point0中,进行计算后就可以得出二维坐标下三维数据应该所在的坐标。

程序由两个文档组成,Transform.py 和 main.py 两部分,第一部分使用了pygame库,如有需要请自行更改实现为其他显示库。第二部分为展示部分,里面还实现了图片3D旋转的程序,使用了opencv库,如有需要可屏蔽或是换为其他库来实现图片的读取和计算。

程序中实现的3D显示包含:立方体,圆,取模字符,任意中文字符和彩色图片的简单3D显示。由于没有进行更高级的三维处理,所以点阵类目标(字符和图片)会出现近处的点或者放大一定倍数后有空隙的情况,如有需要请自行进行更高级的算法处理,比如将画点的大小与三维转换算法结合起来。

程序中任意中文文本的显示使用到了HZK16和HZK32两种字库,注意将路径修改为自己字库的路径下。图片显示中也需要修改图片的路径。

Transform.py 内容如下:

  1 from math import *
2 import pygame
3 from pygame.locals import *
4 import time
5 import sys
6 import binascii #任意中文字符时使用到此库
7
8 '''
9 * 文档: Transform3D.py
10 * 作者: 执念执战
11 * QQ:572314251
12 * 微信:zhinianzhizhan
13 * 原名:王成程
14 * 时间:2019-6
15 * 随梦,随心,随愿,恒执念,为梦执战,执战苍天!
16 *
17 *
18 *
19 * 说明: 本文档是由之前的可以在单片机上实现3D显示的程序修改而来
20 * 直接运行时需要math、time、sys、pygame、binascii 等库的支持
21 * 3D算法从底层一步一步实现
22 * 所有的算法都是使用基本的math库算法实现,没有使用高级的numpy矩阵算法
23 * 所以理论上来说,只要移植好Gui_Point()函数和GUI_Line()函数,去掉需要pygame库支持的部分,
24 * 就可以移植到任意Python环境中(包括可以在单片机上运行的MicroPython环境中),只不过速度有差距
25 *
26 * 转载或使用情注明出处
27 '''
28
29
30
31 FOCAL_DISTANCE = 512 #透视模型
32 '''基于透视投影的基本模型'''
33
34
35
36
37 SCREEN_X_MAX = 800 #屏幕的宽和高
38 SCREEN_Y_MAX = 600
39
40 BLACK=(0,0,0)
41 WHITE=(255,255,255)
42 RED=(255,0,0)
43 GREEN=(0,255,0)
44 BLUE=(0,0,255)
45
46 ForeColor = RED #前景色和背景色
47 BackColor = BLACK
48 #Screen=[[0 for i in range(SCREEN_X_MAX)] for j in range(SCREEN_Y_MAX)] #屏幕缓存
49
50 screen = pygame.display.set_mode((SCREEN_X_MAX,SCREEN_Y_MAX))
51
52 def Gui_Point(x,y,color):
53 '''|**********************************************************
54 |**函数:Gui_Point
55 |**功能:画点函数
56 |**说明:x,y:坐标点
57 | color:颜色
58 | 若想支持其他Python环境,需要完成本函数的移植
59 |
60 |
61 |**作者: 执念执战
62 |**时间:2019-6-3
63 |*********************************************************'''
64 #Screen[(int)(y)][(int)(x)]=color
65 pygame.draw.line(screen,color,(x,y),(x+1,y),2)
66 def GUI_Line(xstart,ystart,xend,yend,color):
67 '''|**********************************************************
68 |**GUI_Line
69 |**功能:画线函数
70 |**说明:xstart,ystart:起始坐标点
71 | xend,yend:结束坐标点
72 | color:颜色
73 | 若想支持其他Python环境,需要完成本函数的移植
74 |
75 |
76 |**作者: 执念执战
77 |**时间:2019-6-3
78 |*********************************************************'''
79 pygame.draw.line(screen,color,(xstart,ystart),(xend,yend),2)
80
81
82
83 class zuobiaostruct:
84 '''坐标结构体'''
85 def __init__(self):
86 self.x=0
87 self.y=0
88 self.z=0
89
90 Cube_Size = 16.0 #立方体基本边长
91 Cube=[zuobiaostruct() for i in range(8)]
92
93 '''
94 相当于正方形的顶点坐标。
95 修改长度可以改为长方形,或是修改边长等。
96 当然,也可修改顶点坐标为任意数据,然后对顶点坐标进行3D运算,最后按照顺序在需要的顶点之间画线,就能生成其他3D图形
97
98 '''
99 Cube[0].x=0.0
100 Cube[0].y=0.0
101 Cube[0].z=0.0
102
103 Cube[1].x=Cube_Size
104 Cube[1].y=0.0
105 Cube[1].z=0.0
106
107 Cube[2].x=0.0
108 Cube[2].y=Cube_Size
109 Cube[2].z=0.0
110
111 Cube[3].x=Cube_Size
112 Cube[3].y=Cube_Size
113 Cube[3].z=0.0
114
115 Cube[4].x=0.0
116 Cube[4].y=0.0
117 Cube[4].z=Cube_Size
118
119 Cube[5].x=Cube_Size
120 Cube[5].y=0.0
121 Cube[5].z=Cube_Size
122
123 Cube[6].x=0.0
124 Cube[6].y=Cube_Size
125 Cube[6].z=Cube_Size
126
127 Cube[7].x=Cube_Size
128 Cube[7].y=Cube_Size
129 Cube[7].z=Cube_Size
130 '''Cube=[[0,0,0],
131 [16,0,0],
132 [0,16,0],
133 [16,16,0],
134
135 [0,0,16],
136 [16,0,16],
137 [0,16,16],
138 [16,16,16]]
139 '''
140
141
142
143
144
145
146 '''
147 -**************************************************************-
148 3D坐标运算部分
149 -**************************************************************-
150 '''
151
152
153
154
155 def MATRIX_copy(sourceMAT):
156 '''|**********************************************************
157 |**函数:MATRIX_copy
158 |**功能:矩阵拷贝
159 |**说明: sourceMAT[4][4](源矩阵,source matrix),
160 | targetMAT[4][4] (目标矩阵 target matrix)
161 | 边学边写
162 |**作者: 执念执战
163 |**时间:2015-11-29,21:52
164 |*********************************************************'''
165 targetMAT=[[0.0 for i in range(4)] for n in range(4)]
166 for a in range(4):
167 for b in range(4):
168 targetMAT[a][b]=sourceMAT[a][b]
169 return targetMAT
170
171 ''
172
173 def MATRIX_multiply(MAT1,MAT2):
174 '''|*******************************************************
175 |**函数:MATRIX_multiply
176 |**功能:矩阵相乘
177 |**说明: MAT1[4][4](矩阵1),MAT2[4][4](矩阵2),
178 | newMAT[4][4] (结果矩阵 )
179 | 边学边写
180 |**作者: 执念执战
181 |**时间:2015-11-29
182 |**********************************************************'''
183 newMAT=[[0.0 for i in range(4)] for n in range(4)]
184 for a in range(4):
185 for b in range(4):
186 newMAT[a][b]=MAT1[a][0]*MAT2[0][b]+MAT1[a][1]*MAT2[1][b]+MAT1[a][2]*MAT2[2][b]+MAT1[a][3]*MAT2[3][b]
187 return newMAT
188
189
190
191 def vector_matrix_MULTIPLY(Source,MAT):
192 '''**********************************************************
193 |**函数: vector_matrix_MULTIPLY
194 |**功能:矢量与矩阵相乘
195 |**说明: Source(源矢量坐标) MAT[][](变换坐标)
196 | 边学边写
197 |**作者: 执念执战
198 |**时间:2015-11-29
199 |***********************************************************'''
200 Result=zuobiaostruct()
201 Result.x=Source.x*MAT[0][0]+Source.y*MAT[1][0]+Source.z*MAT[2][0]+MAT[3][0]
202 Result.y=Source.x*MAT[0][1]+Source.y*MAT[1][1]+Source.z*MAT[2][1]+MAT[3][1]
203 Result.z=Source.x*MAT[0][2]+Source.y*MAT[1][2]+Source.z*MAT[2][2]+MAT[3][2]
204 return Result
205
206
207
208 def structure_3D():
209 '''**********************************************************
210 |**函数: structure_3D
211 |**功能:构造单位矩阵
212 |**说明: 将一个数组构造成单位矩阵(对角线上全为1,其他为0)
213 | 边学边写
214 |**作者: 执念执战
215 |**时间:2015-11-29
216 |*********************************************************'''
217 MAT=[[0.0 for i in range(4)] for i in range(4)]
218 MAT[0][0]=1.0
219 MAT[0][1]=0.0
220 MAT[0][2]=0.0
221 MAT[0][3]=0.0 #// 1 0 0 0
222
223 MAT[1][0]=0.0
224 MAT[1][1]=1.0
225 MAT[1][2]=0.0
226 MAT[1][3]=0.0 #// 0 1 0 0
227
228 MAT[2][0]=0.0
229 MAT[2][1]=0.0
230 MAT[2][2]=1.0
231 MAT[2][3]=0.0
232 #// 0 0 1 0
233 MAT[3][0]=0.0
234 MAT[3][1]=0.0
235 MAT[3][2]=0.0
236 MAT[3][3]=1.0
237 #// 0 0 0 1
238
239 return MAT
240
241
242
243 def Translate3D(MAT,tx, ty, tz):
244 '''********************************************************
245 |**函数: Translate3D
246 |**功能:平移变换矩阵
247 |**说明: 1:tx,ty,tz 为平移参数
248 | 2:当为边长的一半的倒数时,图像绕着自己旋转,即原点在中心
249 |
250 | 边学边写
251 |**作者: 执念执战
252 |**时间:2015-11-29
253 |**********************************************************'''
254 tMAT=[[0.0 for i in range(4)] for i in range(4)]
255 tMAT[0][0]=1
256 tMAT[0][1]=0
257 tMAT[0][2]=0
258 tMAT[0][3]=0 #// 1 0 0 tx
259
260 tMAT[1][0]=0
261 tMAT[1][1]=1
262 tMAT[1][2]=0
263 tMAT[1][3]=0 #// 0 1 0 ty
264
265 tMAT[2][0]=0
266 tMAT[2][1]=0
267 tMAT[2][2]=1
268 tMAT[2][3]=0 #// 0 0 1 tz
269
270 tMAT[3][0]=tx
271 tMAT[3][1]=ty
272 tMAT[3][2]=tz
273 tMAT[3][3]=1; #// 0 0 0 1
274
275 return MATRIX_multiply(MAT,tMAT)#//相乘
276
277
278
279 def Scale_3D( MAT, sx, sy, sz):
280 '''*******************************************************
281 |**函数: Scale_3D
282 |**功能:比例(scale)变换矩阵
283 |**说明: 1:相对于原点上的比例变换
284 | 2:sx,sy,sz 是对应轴上的缩放量
285 | 3:矩阵根据三个比例进行比例变换
286 | 边学边写
287 |**作者: 执念执战
288 |**时间:2015-11-30,7:45
289 |*********************************************************'''
290 tMAT=[[0.0 for i in range(4)] for i in range(4)]
291 tMAT[0][0]=sx
292 tMAT[0][1]=0
293 tMAT[0][2]=0
294 tMAT[0][3]=0 #// sx0 0 0
295 tMAT[1][0]=0
296 tMAT[1][1]=sy
297 tMAT[1][2]=0
298 tMAT[1][3]=0 #// 0 sy0 0
299 tMAT[2][0]=0
300 tMAT[2][1]=0
301 tMAT[2][2]=sz
302 tMAT[2][3]=0 #// 0 0 sz0
303 tMAT[3][0]=0
304 tMAT[3][1]=0
305 tMAT[3][2]=0
306 tMAT[3][3]=1 #// 0 0 0 1
307 return MATRIX_multiply(MAT,tMAT) # //相乘
308
309
310
311
312
313
314 def Rotate_3D( MAT, ax, ay, az):
315 '''**********************************************************/
316 |**函数: Rotate_3D
317 |**功能:旋转变换矩阵
318 |**说明: 1:绕z轴旋转az度角
319 | 2:az为旋转的角度量,赋正值为顺时针转
320 | 3:矩阵MAT根据AZ度角进行旋转变换
321 | 边学边写
322 |**作者: 执念执战
323 |**时间:2015-11-30,7:45
324 |**********************************************************'''
325 MAT1=[[0.0 for i in range(4)] for i in range(4)]
326 MAT2=[[0.0 for i in range(4)] for i in range(4)]
327 MATx=[[0.0 for i in range(4)] for i in range(4)]
328 MATy=[[0.0 for i in range(4)] for i in range(4)]
329 MATz=[[0.0 for i in range(4)] for i in range(4)]
330
331 ax=(3.1415926*ax)/180.0 #//角度转换为弧度量
332 ay=(3.1415926*ay)/180.0
333 az=(3.1415926*az)/180.0
334 '''/*****************************绕x轴旋转********************************************/'''
335
336 MATx[0][0]=1
337 MATx[0][1]=0
338 MATx[0][2]=0
339 MATx[0][3]=0 #//1 0 0 0
340 MATx[1][0]=0
341 MATx[1][1]=cos(ax)
342 MATx[1][2]=-sin(ax)
343 MATx[1][3]=0 #//0 cos(ax) -sin(ax) 0
344 MATx[2][0]=0
345 MATx[2][1]=sin(ax)
346 MATx[2][2]=cos(ax)
347 MATx[2][3]=0 #//0 sin(ax) cos(ax) 0
348 MATx[3][0]=0
349 MATx[3][1]=0
350 MATx[3][2]=0
351 MATx[3][3]=1 #//0 0 0 1
352
353 '''/*****************************绕y轴旋转********************************************/'''
354 MATy[0][0]=cos(ay)
355 MATy[0][1]=0
356 MATy[0][2]=sin(ay)
357 MATy[0][3]=0 #//cos(ay) 0 sin(ay) 0
358 MATy[1][0]=0
359 MATy[1][1]=1
360 MATy[1][2]=0
361 MATy[1][3]=0 #// 0 1 0 0
362 MATy[2][0]=-sin(ay)
363 MATy[2][1]=0
364 MATy[2][2]=cos(ay)
365 MATy[2][3]=0 #// -sin(ay) 0 cos(ay) 0
366 MATy[3][0]=0
367 MATy[3][1]=0
368 MATy[3][2]=0
369 MATy[3][3]=1 #// 0 0 0 1
370
371
372 '''/*****************************绕z轴旋转********************************************/'''
373 MATz[0][0]=cos(az)
374 MATz[0][1]=-sin(az)
375 MATz[0][2]=0
376 MATz[0][3]=0 #//cos(az) -sin(az) 0 0
377 MATz[1][0]=sin(az)
378 MATz[1][1]=cos(az)
379 MATz[1][2]=0
380 MATz[1][3]=0 #// sin(az) cos(az) 0 0
381 MATz[2][0]=0
382 MATz[2][1]=0
383 MATz[2][2]=1
384 MATz[2][3]=0 #// 0 0 1 0
385 MATz[3][0]=0
386 MATz[3][1]=0
387 MATz[3][2]=0
388 MATz[3][3]=1 #// 0 0 0 1
389
390 MAT1=MATRIX_multiply(MAT,MATx)
391 MAT2=MATRIX_multiply(MAT1,MATy)
392 return MATRIX_multiply(MAT2,MATz)
393 #return MAT
394
395 '''
396 /********************************************************************************/
397 /*------------------------------------------------------------------------------*/
398 /* 投影算法 三维转二维的相关函数 */
399 /*------------------------------------------------------------------------------*/
400 /********************************************************************************/
401 '''
402
403
404
405
406
407 def OrtProject(Space):
408 '''********************************************************
409 |**函数: OrtProject
410 |**功能:透视投影(Perspective projection)
411 |**说明:简单透视
412
413 | 边学边写
414 |**作者: 执念执战
415 |**时间:2015-11-30
416 |*********************************************************'''
417 Screen=zuobiaostruct()
418 Screen.x=(int)(Space.x)
419 Screen.y=(int)(Space.y)
420
421 return Screen;
422
423
424
425 def PerProject( Space, XO, YO):
426 '''**********************************************************/
427 |**函数: PerProject
428 |**功能:透视投影(Perspective projection)
429 |**说明:XO,YO为投影后的图形中心的屏幕坐标
430
431 | 边学边写
432 |**作者: 执念执战
433 |**时间:2015-11-30
434 |********************************************************'''
435
436 Screen=zuobiaostruct()
437 if (Space.z==0):
438 Space.z=0.01 #//被除数不能为零
439 Screen.x=(int)(FOCAL_DISTANCE*Space.x /(Space.z+FOCAL_DISTANCE)+XO)
440 Screen.y=(int)(FOCAL_DISTANCE*Space.y /(Space.z+FOCAL_DISTANCE)+YO)
441 return Screen
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457 def RateCube_size( sx, sy, sz, x,y,color,X_Size=1,Y_Size=1,Z_Size=1, ratio=1):
458 '''**********************************************************/
459 |**函数: RateCube_size
460 |**功能:显示3D的立方体
461 |**说明:sx,sy,sz :角度值
462 | x,y: 欲显示的坐标位置
463 | X_Size,Y_Size,Z_Size:立方体的三个边长,默认为1
464 | ratio:放大比例
465
466 |
467 |**作者: wcc 执念执战
468 |**时间:2019-6-3
469 |********************************************************'''
470 gMAT=[[0.0 for i in range(4)] for n in range(4)]
471 temp=zuobiaostruct()
472 Cube_dis=[zuobiaostruct() for i in range(8)]
473
474
475
476
477 gMAT=structure_3D() #//构造为单位矩阵
478 gMAT=Translate3D(gMAT,-10,-8,-8) #//平移变换矩阵,当为边长的一半的倒数时,图像绕着自己旋转,即原点在中心
479 gMAT=Scale_3D(gMAT,X_Size*ratio,Y_Size*ratio,Z_Size*ratio) #//比例变换矩阵
480 gMAT=Rotate_3D(gMAT,sx,sy,sz) #//旋转变换矩阵
481 gMAT=Translate3D(gMAT,8,8,8) #//平移变换矩阵 x:调节距离中心点的位置,相当于下面Point0.z
482 #// y:上下调动位置 ,具体根据实际修改
483
484
485 for i in range(8):
486
487
488 temp=vector_matrix_MULTIPLY(Cube[i],gMAT)# //矢量与矩阵相乘
489 Cube_dis[i]=PerProject(temp,0,0)# //正射投影 xo,yo:position
490 Cube_dis[i].x+=x
491 Cube_dis[i].y+=y
492 #Cube_dis[i].x+=SCREEN_X_MAX
493 #Cube_dis[i].y+=SCREEN_Y_MAX
494
495
496 '''将目标顶点按照预期连接起来'''
497 GUI_Line(Cube_dis[0].x,Cube_dis[0].y,Cube_dis[1].x,Cube_dis[1].y,color)
498 GUI_Line(Cube_dis[0].x,Cube_dis[0].y,Cube_dis[2].x,Cube_dis[2].y,color)
499 GUI_Line(Cube_dis[3].x,Cube_dis[3].y,Cube_dis[1].x,Cube_dis[1].y,color)
500 GUI_Line(Cube_dis[3].x,Cube_dis[3].y,Cube_dis[2].x,Cube_dis[2].y,color)
501
502
503 GUI_Line(Cube_dis[0+4].x,Cube_dis[0+4].y,Cube_dis[1+4].x,Cube_dis[1+4].y,color)
504 GUI_Line(Cube_dis[0+4].x,Cube_dis[0+4].y,Cube_dis[2+4].x,Cube_dis[2+4].y,color)
505 GUI_Line(Cube_dis[3+4].x,Cube_dis[3+4].y,Cube_dis[1+4].x,Cube_dis[1+4].y,color)
506 GUI_Line(Cube_dis[3+4].x,Cube_dis[3+4].y,Cube_dis[2+4].x,Cube_dis[2+4].y,color)
507
508
509 GUI_Line(Cube_dis[0].x,Cube_dis[0].y,Cube_dis[0+4].x,Cube_dis[0+4].y,color)
510 GUI_Line(Cube_dis[1].x,Cube_dis[1].y,Cube_dis[1+4].x,Cube_dis[1+4].y,color)
511 GUI_Line(Cube_dis[2].x,Cube_dis[2].y,Cube_dis[2+4].x,Cube_dis[2+4].y,color)
512 GUI_Line(Cube_dis[3].x,Cube_dis[3].y,Cube_dis[3+4].x,Cube_dis[3+4].y,color)
513
514
515
516
517
518 Last_flg1=False
519 Last_flg2=False
520 Last_x1=0
521 Last_y1=0
522
523 Last_x2=0
524 Last_y2=0
525
526
527 def Rotatecircle( ax, ay, az,x, y,Z_Size, r, color ):
528 '''**********************************************************/
529 |**函数: Rotatecircle
530 |**功能:显示3D的圆
531 |**说明:sx,sy,sz :角度值
532 | x,y: 欲显示的坐标位置
533 | Z_Size:距旋转轴的距离
534 | r:半径
535 | color:颜色
536
537 |
538 |**作者: wcc 执念执战
539 |**时间:2019-6-3
540 |********************************************************'''
541
542 global Last_flg1
543 global Last_flg2
544 global Last_x1,Last_y1,Last_x2,Last_y2
545
546 gMAT=[[0.0 for i in range(4)] for n in range(4)]
547 Point0=zuobiaostruct()
548 Point3=zuobiaostruct()
549
550 Point1=zuobiaostruct()
551 PointDis=zuobiaostruct()
552
553 gMAT=structure_3D() #//构造单位矩阵
554 gMAT=Translate3D(gMAT,-r,0,0) #//平移变换矩阵
555 gMAT=Scale_3D(gMAT,3,3,3) #//比例变换矩阵
556 gMAT=Rotate_3D(gMAT,ax,ay,az) #//旋转变换矩阵
557 #gMAT=Translate3D(gMAT,-r/2,-r/2,-r/2) #//平移变换矩阵
558
559
560
561 for i in range(0,r+r+1):
562
563 Point0.x=i
564 Point0.y=r-(r-sqrt(r*r-(r-i)*(r-i)))
565 Point0.z=0#Point0.z+Z_Size
566 Point3.x=i
567 Point3.y=r-(r+sqrt(r*r-(r-i)*(r-i)))
568 Point3.z=0#Point3.z+Z_Size
569
570
571 Point1=vector_matrix_MULTIPLY(Point0,gMAT) #//矢量与矩阵相乘
572 PointDis=PerProject(Point1,0,0) #//映射投影
573 #PointDis.x+=SCREEN_X_MAX
574 #PointDis.y+=SCREEN_Y_MAX #//用来解决超出屏幕后乱码的问题。去掉后顺时针转到超出左边界后会找不到坐标无限划线,
575 #// 还要注意图像不要大到超过两个屏
576
577 if Last_flg1 == True and i!=0:
578 GUI_Line(PointDis.x+x,PointDis.y+y,Last_x1+x,Last_y1+y,color) #连接上次的保存,避免点的空隙过大
579 else:
580 GUI_Line(PointDis.x+x,PointDis.y+y,PointDis.x+1+x,PointDis.y+1+y,color)
581 Last_x1= PointDis.x
582 Last_y1= PointDis.y
583 Last_flg1=True
584
585 Point1=vector_matrix_MULTIPLY(Point3,gMAT) #//矢量与矩阵相乘
586 PointDis=PerProject(Point1,0,0) #//映射投影
587
588 #PointDis.x+=SCREEN_X_MAX
589 # PointDis.y+=SCREEN_Y_MAX #//用来解决超出屏幕后乱码的问题。去掉后顺时针转到超出左边界后会找不到坐标无限划线,
590 if Last_flg2 == True and i!=0:
591 GUI_Line(PointDis.x+x,PointDis.y+y,Last_x2+x,Last_y2+y,color)#连接上次的保存,避免点的空隙过大
592 else:
593 GUI_Line(PointDis.x+x,PointDis.y+y,PointDis.x+1+x,PointDis.y+1+y,color)
594 Last_x2= PointDis.x
595 Last_y2= PointDis.y
596 Last_flg2=True
597
598
599 SETCH32X29=[[0 for i in range(128)] for i in range(4)]
600
601 '''// 设置宋体小二常规, 参数中的其他选项为纵向取模,字节倒序,保留,任何时候都加零'''
602 ''' 本字符集为 宽29 高 32的字符,使用时注意 32/8'''
603
604 '''
605 /*-- 执--*/
606 /*-- 29 x32 ---*/
607 '''
608 SETCH32X29[0]=(0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFC,0x04,0x80,0x80,0x00,0x00,0x00,0xFC,
609 0xFC,0xFC,0x08,0x00,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
610 0x81,0x81,0x81,0xFF,0xFF,0xFF,0x61,0x23,0xB3,0x93,0x82,0x82,0xFF,0xFF,0xFF,0x02,
611 0x02,0xFF,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x01,0x01,
612 0xFF,0xFF,0xFF,0x00,0x00,0x80,0xE0,0xF9,0x7F,0x1F,0x07,0x0E,0x1E,0x1C,0x1F,0x7F,
613 0xFF,0xF0,0x80,0xC0,0xF8,0xF8,0x00,0x00,0x00,0x02,0x02,0x06,0x0E,0x0F,0x0F,0x0B,
614 0x0C,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,
615 0x07,0x07,0x07,0x00,
616 )
617
618 '''/*-- 念 --*/
619 /*-- 29 x32 ---*/'''
620 SETCH32X29[1]=(
621 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF8,0xFC,0xBE,0x1E,0x3C,
622 0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x30,
623 0x18,0x18,0x0C,0x26,0x27,0x23,0x21,0x21,0x20,0x21,0x27,0x2F,0x2F,0x24,0xE0,0xF1,
624 0xF1,0x73,0x27,0x06,0x0E,0x0E,0x0C,0x0C,0x04,0x00,0x00,0x00,0x80,0xC0,0xF0,0xF8,
625 0x78,0x00,0xFC,0xFC,0xFC,0x0B,0x0F,0x3E,0x3C,0x1E,0x07,0x07,0x03,0xE0,0xE0,0x88,
626 0x38,0xF8,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x07,
627 0x07,0x07,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x07,0x07,0x07,0x02,0x00,0x01,
628 0x01,0x00,0x00,0x00, )
629
630 '''/*-- 执--*/
631 /*-- 29 x32 ---*/'''
632 SETCH32X29[2]=(
633
634 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFC,0x04,0x80,0x80,0x00,0x00,0x00,0xFC,
635 0xFC,0xFC,0x08,0x00,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
636 0x81,0x81,0x81,0xFF,0xFF,0xFF,0x61,0x23,0xB3,0x93,0x82,0x82,0xFF,0xFF,0xFF,0x02,
637 0x02,0xFF,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x01,0x01,
638 0xFF,0xFF,0xFF,0x00,0x00,0x80,0xE0,0xF9,0x7F,0x1F,0x07,0x0E,0x1E,0x1C,0x1F,0x7F,
639 0xFF,0xF0,0x80,0xC0,0xF8,0xF8,0x00,0x00,0x00,0x02,0x02,0x06,0x0E,0x0F,0x0F,0x0B,
640 0x0C,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,
641 0x07,0x07,0x07,0x00, )
642 '''/*-- 战 --*/
643 /*-- 29 x32 ---*/'''
644 SETCH32X29[3]=(
645
646 0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0xFC,0x08,0x00,0x00,0x80,0x80,0x80,0x00,
647 0xFE,0xFE,0xFC,0x04,0x08,0x18,0x70,0xF0,0xF0,0x60,0x00,0x00,0x00,0x00,0x00,0xC0,
648 0xC0,0x80,0x80,0xFF,0xFF,0xFF,0x81,0x81,0xC9,0xC9,0xC9,0x89,0x0D,0x0F,0xFF,0xFF,
649 0xF4,0x04,0x04,0xC4,0xF6,0xF7,0x63,0x66,0x04,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x80,
650 0x80,0x80,0x80,0x80,0x80,0xFF,0xFF,0xFF,0x00,0x00,0x80,0xC3,0xFF,0x7F,0xFC,0xFF,
651 0xCF,0x07,0x01,0xF0,0xF0,0x00,0x00,0x00,0x00,0x07,0x03,0x03,0x00,0x00,0x00,0x00,
652 0x00,0x08,0x0B,0x0F,0x07,0x06,0x03,0x01,0x01,0x00,0x00,0x00,0x01,0x03,0x07,0x07,
653 0x0F,0x0F,0x08,0x00,)
654
655
656
657
658
659
660
661
662
663
664 def Show3DCharXxY(dp,dp_x,dp_y,ax,ay,az,x,y,Z_Size,color):
665 '''**********************************************************/
666 |**函数: Show3DCharXxY
667 |**功能:显示3D字体,需要自己取模,支持任意python环境
668 |**说明:dp:字体数组的名称,为需要取模的字体。如上面的 SETCH32X29[]数组
669 取模方式:设置宋体小二常规, 参数中的其他选项为纵向取模,字节倒序,保留,任何时候都加零
670 dp_x,dp_y:取模字体的长宽,比如32x29的字符为:29,32/4,因为保存的字符格式为列项一个字节表示8个像素点,具体参考取模原理
671 | ax,ay,az:角度值
672 | x,y: 欲显示的坐标位置
673 | Z_Size:距旋转轴的距离
674 | color:颜色
675
676 |
677 |**作者: wcc 执念执战
678 |**时间:2019-6-3
679 |********************************************************'''
680
681 gMAT=[[0.0 for i in range(4)] for n in range(4)]
682 Point0=zuobiaostruct()
683 Point1=zuobiaostruct()
684 PointDis=zuobiaostruct()
685
686 gMAT=structure_3D() #//构建单位矩阵
687 gMAT=Translate3D(gMAT,-16,-12,-6); #//平移变换矩阵
688 gMAT=Scale_3D(gMAT,4,4,4); #//比例变换矩阵
689 gMAT=Rotate_3D(gMAT,ax,ay,az); #//旋转变换矩阵
690 #gMAT=Translate3D(gMAT,0,-8,8); #//平移变换矩阵 x:调节距离中心点的位置,相当于下面Point0.z
691 #//y:上下调动位置 ,具体根据实际修改
692
693
694
695 for i in range(dp_y):
696 for k in range(8):
697 temp = 0x01 << k
698 for j in range(dp_x):
699 data=dp[i*dp_x+j]
700 if data & temp == temp:
701
702 Point0.x=j
703 Point0.y=(i*8)+k
704 Point0.z =Z_Size #//此参数能够改变字符距离旋转轴中心的距离
705
706 Point1=vector_matrix_MULTIPLY(Point0,gMAT)#//矢量与矩阵相乘
707 PointDis=PerProject(Point1,0,0) #//映射投影
708 #PointDis.x+=SCREEN_X_MAX
709 #PointDis.y+=SCREEN_Y_MAX #//用来解决超出屏幕后乱码的问题。去掉后顺时针转到超出左边界后会找不到坐标无限划线,
710 Gui_Point(PointDis.x+x,PointDis.y+y,color)
711
712
713
714
715
716
717 def Show3D16x16Font(font,ax,ay,az,x,y,Z_Size,frontcolor,backcolor,model=0):
718 '''**********************************************************/
719 |**函数: Show3D16x16Font
720 |**功能:显示3D的16x16字符,为从汉字库读取的字符数据,支持数千个汉字
721 | 本函数需要 binascii 库的支持,不支持此库的环境无法运行本函数
722 |**说明:font:欲显示的汉字,目前只支持一个字符的显示,只支持汉字的显示
723 | sx,sy,sz :角度值
724 | x,y: 欲显示的坐标位置
725 | Z_Size:距旋转轴的距离
726 | frontcolor,backcolor:颜色,前景色和背景色
727 | model:显示模式,只有模式为1时才填充背景色,否则只填充前景色
728 |
729 |**作者: wcc 执念执战
730 |**时间:2019-6-3
731 |********************************************************'''
732 length = len(font)
733 if length == 1: #只支持一个支付的显示
734 text = font
735 else:
736 return
737 gb2312 = text.encode('gb2312')
738 hex_str = binascii.b2a_hex(gb2312)
739 result = str(hex_str,encoding = 'utf-8' )
740
741 area = eval('0x' + result[:2]) - 0xA0
742 index = eval('0x' + result[2:]) - 0xA0
743 offset = (94 * (area - 1)+ (index - 1))*32
744 font_rect = None
745 with open("D:/Mystudy/Python/pyGame/HZK16","rb") as f: #16x16字符集的地址
746 f.seek(offset)
747 font_rect = f.read(32)
748 f.close()
749
750 gMAT=[[0.0 for i in range(4)] for n in range(4)]
751 Point0=zuobiaostruct()
752 Point1=zuobiaostruct()
753 PointDis=zuobiaostruct()
754
755 gMAT=structure_3D() #//构建单位矩阵
756 gMAT=Translate3D(gMAT,-8,-8,-8); #//平移变换矩阵
757 gMAT=Scale_3D(gMAT,4,4,4); #//比例变换矩阵
758 gMAT=Rotate_3D(gMAT,ax,ay,az); #//旋转变换矩阵
759 #gMAT=Translate3D(gMAT,8,8,8); #//平移变换矩阵 x:调节距离中心点的位置,相当于下面Point0.z
760
761
762
763 i=0
764 k=0
765 j=0
766 XO=0
767 YO=0
768
769 for i in range(16):
770 for k in range(8):
771 temp = 0x01 << k
772 for j in range(2):
773 data=font_rect[i*2+j]
774 if data & temp == temp:
775
776 Point0.x=16-(k+(1-j)*8)
777 Point0.y=i #(i*8)+k
778 Point0.z=Z_Size #//此参数能够改变字符距离旋转轴中心的距离
779
780 Point1=vector_matrix_MULTIPLY(Point0,gMAT)#//矢量与矩阵相乘
781 PointDis=PerProject(Point1,XO,YO) #//映射投影
782 #PointDis.x+=SCREEN_X_MAX
783 #PointDis.y+=SCREEN_Y_MAX #//用来解决超出屏幕后乱码的问题。去掉后顺时针转到超出左边界后会找不到坐标无限划线,
784 Gui_Point(PointDis.x+x,PointDis.y+y,frontcolor)
785 else:
786 if model ==1: #模式为1 时才会绘制底色
787 Point0.x=16-(k+(1-j)*8)
788 Point0.y=i #(i*8)+k
789 Point0.z=Z_Size #//此参数能够改变字符距离旋转轴中心的距离
790
791 Point1=vector_matrix_MULTIPLY(Point0,gMAT)#//矢量与矩阵相乘
792 PointDis=PerProject(Point1,XO,YO) #//映射投影
793 #PointDis.x+=SCREEN_X_MAX
794 #PointDis.y+=SCREEN_Y_MAX #//用来解决超出屏幕后乱码的问题。去掉后顺时针转到超出左边界后会找不到坐标无限划线,
795 Gui_Point(PointDis.x+x,PointDis.y+y,backcolor)
796
797
798
799
800
801
802
803
804 def Show3D32x32Font(font,ax,ay,az,x,y,Z_Size,frontcolor,backcolor,model=0):
805 '''**********************************************************/
806 |**函数: Show3D32x32Font
807 |**功能:显示3D的32x32字符,为从汉字库读取的字符数据,支持数千个汉字
808 | 本函数需要 binascii 库的支持,不支持此库的环境无法运行本函数
809 |**说明:font:欲显示的汉字,目前只支持一个字符的显示,只支持汉字的显示
810 | sx,sy,sz :角度值
811 | x,y: 欲显示的坐标位置
812 | Z_Size:距旋转轴的距离
813 | frontcolor,backcolor:颜色,前景色和背景色
814 | model:显示模式,只有模式为1时才填充背景色,否则只填充前景色
815 |
816 |**作者: wcc 执念执战
817 |**时间:2019-6-3
818 |********************************************************'''
819 length = len(font)
820 if length == 1: #只支持一个支付的书写
821 text = font
822 else:
823 return
824 gb2312 = text.encode('gb2312')
825 hex_str = binascii.b2a_hex(gb2312)
826 result = str(hex_str,encoding = 'utf-8' )
827
828 area = eval('0x' + result[:2]) - 0xA0
829 index = eval('0x' + result[2:]) - 0xA0
830 offset = (94 * (area - 1)+ (index - 1))*32*4
831 font_rect = []*32*4
832 with open("D:/Mystudy/Python/pyGame/HZK32zkkh","rb") as f:#32x32字符集的地址,HZK32wryh 为微软雅黑字体,HZK32zkkh为站酷酷黑字体
833 f.seek(offset)
834 font_rect = f.read(32*4)
835 f.close()
836
837 gMAT=[[0.0 for i in range(4)] for n in range(4)]
838 #temp=zuobiaostruct()
839 Point0=zuobiaostruct()
840 Point1=zuobiaostruct()
841 PointDis=zuobiaostruct()
842
843 gMAT=structure_3D() #//构建单位矩阵
844 gMAT=Translate3D(gMAT,-16,-12,-6); #//平移变换矩阵,能够调节字体相对中心轴的位置
845 gMAT=Scale_3D(gMAT,4,4,4); #//比例变换矩阵
846 gMAT=Rotate_3D(gMAT,ax,ay,az); #//旋转变换矩阵
847 #gMAT=Translate3D(gMAT,8,8,8); #//平移变换矩阵 x:调节距离中心点的位置,相当于下面Point0.z
848
849
850
851 i=0
852 k=0
853 j=0
854 XO=0
855 YO=0
856
857 for i in range(32):
858 for k in range(8):
859 temp = 0x01 << k
860 for j in range(4):
861 data=font_rect[i*4+j]
862 if data & temp == temp:
863
864 Point0.x=32-(k+(3-j)*8)
865 Point0.y=i #(i*8)+k
866 Point0.z=Z_Size #//此参数能够改变字符距离旋转轴中心的距离
867
868 Point1=vector_matrix_MULTIPLY(Point0,gMAT)#//矢量与矩阵相乘
869 PointDis=PerProject(Point1,XO,YO) #//映射投影
870 #PointDis.x+=SCREEN_X_MAX
871 #PointDis.y+=SCREEN_Y_MAX #//用来解决超出屏幕后乱码的问题。去掉后顺时针转到超出左边界后会找不到坐标无限划线,
872 Gui_Point(PointDis.x+x,PointDis.y+y,frontcolor)
873 else:
874 if model ==1: #模式为1 时才会绘制底色
875 Point0.x=32-(k+(3-j)*8)
876 Point0.y=i #(i*8)+k
877 Point0.z=Z_Size #//此参数能够改变字符距离旋转轴中心的距离
878
879 Point1=vector_matrix_MULTIPLY(Point0,gMAT)#//矢量与矩阵相乘
880 PointDis=PerProject(Point1,XO,YO) #//映射投影
881 #PointDis.x+=SCREEN_X_MAX
882 #PointDis.y+=SCREEN_Y_MAX #//用来解决超出屏幕后乱码的问题。去掉后顺时针转到超出左边界后会找不到坐标无限划线,
883 Gui_Point(PointDis.x+x,PointDis.y+y,backcolor)
884
885
886
887
888
889
890
891
892 def example_1(ax,ay,az,x,y,char1,char2,forecolor,backcolor):
893 '''**********************************************************/
894 |**函数: example_1
895 |**功能:旋转立方体 + 旋转字符,字符为取模字符,支持取模,支持其他Python环境
896 | 只能显示取模字体
897 |**说明:
898 | ax,ay,az :角度值
899 | x,y: 欲显示的坐标位置
900 char1,char2:切换显示哪个字符
901 | Z_Size:距旋转轴的距离
902 | frontcolor,backcolor:颜色,前景色和背景色
903 |
904 |
905 |**作者: wcc 执念执战
906 |**时间:2019-6-3
907 |********************************************************'''
908 RateCube_size(ax,ay,az,x,y,forecolor,8,8,8,1)
909 RateCube_size(ax,ay+45,az,x,y,forecolor,12,12,12,1)
910
911 Show3DCharXxY(SETCH32X29[char1],29,4,ax,ay,az,x,y,-12,forecolor)
912 Show3DCharXxY(SETCH32X29[char2],29,4,ax,ay-90,az,x,y,-12,forecolor)
913
914 def example_2(ax,ay,az,x,y,char1,char2,forecolor,backcolor):
915 '''**********************************************************/
916 |**函数: example_2
917 |**功能:旋转立方体 + 旋转字符,字符为字符集,需要库支持,需要字符集支持
918 | 修改内部的 char 字符串可现实任意(字符集所支持的)中文字符
919 |**说明:
920 | ax,ay,az :角度值
921 | x,y: 欲显示的坐标位置
922 char1,char2:切换显示哪个字符
923 | Z_Size:距旋转轴的距离
924 | frontcolor,backcolor:颜色,前景色和背景色
925 |
926 |
927 |**作者: wcc 执念执战
928 |**时间:2019-6-3
929 |********************************************************'''
930
931 char="执念执战"
932 RateCube_size(ax,ay,az,x,y,forecolor,8,8,8,1)
933 RateCube_size(ax,ay,az,x,y,forecolor,12,12,12,1)
934
935 Show3D32x32Font(char[char1],ax,ay%90,az,x,y,-12,forecolor,backcolor,0)
936 Show3D32x32Font(char[char2],ax,ay%90-90,az,x,y,-12,forecolor,backcolor,0)
937
938 def example_3(ax,ay,az,x,y,char1,char2,forecolor,backcolor):
939 '''**********************************************************/
940 |**函数: example_3
941 |**功能:旋转的16x16的中文字符串
942 | 修改内部的 char 字符串可现实任意(字符集所支持的)中文字符
943 |**说明:
944 | ax,ay,az :角度值
945 | x,y: 欲显示的坐标位置
946 char1,char2:切换显示哪个字符
947 | Z_Size:距旋转轴的距离
948 | frontcolor,backcolor:颜色,前景色和背景色
949 |
950 |
951 |**作者: wcc 执念执战
952 |**时间:2019-6-3
953 |********************************************************'''
954 char="任意中文字符测试"
955 length = len(char)
956 for i in range(length):
957 Show3D16x16Font(char[i],ax,ay,az,x+16*4*i,y,2,forecolor,backcolor,0)
958
959

main.py 内容如下:

  1 # -*- coding: utf-8 -*-
2 """
3 Created on Mon Jun 3 14:41:48 2019
4
5 @author: Administrator
6 """
7
8
9 from Transform3D import *
10 import cv2
11
12 def Pic3DShow(ax,ay,az,x,y,size):
13 '''**********************************************************/
14 |**函数: Pic3DShow
15 |**功能:显示3D图片
16 |**说明:ax,ay,az:旋转角度
17 | x,y:显示位置
18 | size:放大倍数
19 本函数由于是使用的基础运算符,没有加速,所以图片过大时,占用运算资源较多
20 修改为numpy来进行运算会快
21 |
22 |**作者: wcc 执念执战
23 |**时间:2019-6-3
24 |********************************************************'''
25
26
27 color1=[0,0,0]
28 img=cv2.imread("D:/Mystudy/Python/pyGame/python.png")
29 width=img.shape[1]
30 height=img.shape[0]
31
32 gMAT=[[0.0 for i in range(4)] for n in range(4)]
33 Point0=zuobiaostruct()
34 Point1=zuobiaostruct()
35 PointDis=zuobiaostruct()
36
37 gMAT=structure_3D() #//构建单位矩阵
38 gMAT=Translate3D(gMAT,-(width/2),-(height/2),0); #//平移变换矩阵,绕着中心轴转
39 gMAT=Scale_3D(gMAT,size,size,size); #//比例变换矩阵,放大多少倍
40 gMAT=Rotate_3D(gMAT,ax,ay,az); #//旋转变换矩阵
41
42
43 for i in range(width):
44 for j in range(height):
45 color=img[j][i]
46 color1[0]=color[2] #将 opencv的BGR颜色转换为正常的RGB颜色
47 color1[1]=color[1]
48 color1[2]=color[0]
49 Point0.x=i
50 Point0.y=j
51 Point0.z=0
52 Point1=vector_matrix_MULTIPLY(Point0,gMAT)
53 PointDis=PerProject(Point1,0,0)
54 Gui_Point(PointDis.x+x,PointDis.y+y,color1)
55
56
57
58 SCREEN_X_MAX = 800 #屏幕的宽和高
59 SCREEN_Y_MAX = 600
60
61 BLACK=(0,0,0)
62 WHITE=(255,255,255)
63 RED=(255,0,0)
64 GREEN=(0,255,0)
65 BLUE=(0,0,255)
66
67 ForeColor = RED #前景色和背景色
68 BackColor = BLACK
69
70
71 pygame.init()
72 sx=0
73 sy=0
74 sz=0
75 turn=0
76 flg1=0
77 flg2=1
78 screen = pygame.display.set_mode((SCREEN_X_MAX,SCREEN_Y_MAX))
79
80 while True:
81 for event in pygame.event.get():
82 if event.type in (QUIT,KEYDOWN):
83 pygame.quit()
84 sys.exit()
85
86 sx+=1
87 sy+=1
88 sz+=1
89 turn+=1
90 if sy>89:
91 sy=0
92 flg1+=1
93 flg2+=1
94 if flg1>3:
95 flg1=0
96 if flg2>3:
97 flg2=0
98 screen.fill(BackColor)
99 example_1(0,sy,0,SCREEN_X_MAX/4,SCREEN_Y_MAX/2,flg1,flg2,ForeColor,BackColor)
100 example_2(0,sy,0,SCREEN_X_MAX/2+100,SCREEN_Y_MAX/2,flg1,flg2,ForeColor,BackColor)
101 example_3(0,turn,0,SCREEN_X_MAX/4,100,flg1,flg2,ForeColor,BackColor)
102 Pic3DShow(0,turn,0,100,100,3)
103 pygame.display.update()
104 #time.sleep(30/1000) #延时,防止速度过快
105

所有的代码都有基本注释,如果想要了解更详细的的3D算法的实现可以参考https://wenku.baidu.com/view/ba9e9e64783e0912a2162ab2.html 等3维计算原理的讲解。

本文代码和字库及图片打包见 附件

本文水平有限,内容很多词语由于知识水平问题不严谨或很离谱,但主要作为记录作用,能理解就好了,希望以后的自己和路过的大神对必要的错误提出批评与指点,对可笑的错误不要嘲笑,指出来我会改正的。

另外,转载使用请注明出处。

-------------随梦,随心,随愿,执念执战,执战苍天!

 

最新文章

  1. 了解HTML CSS选择器操作和特性
  2. flex acionscript png图片去除多余空白,生成合适大小图片
  3. JavaScript prototype应用
  4. Spring 教程(二)
  5. Python的面向对象3
  6. Devexpress 使用经验 —— ASPxGridView前后台交互写法推荐
  7. w10 系统升级
  8. wp如何代码实现锁屏
  9. Python 面向对象(五) 描述器
  10. (一)Qt5模块,QtCreator常用快捷键,命名规范
  11. 2017-2018-2 20155228 《网络对抗技术》 实验一:PC平台逆向破解
  12. spring-mvc(基础)
  13. jQuery 实现图片动画代码
  14. App 开发步骤
  15. IIS 部署 Python Django网站流程(受够了野路子)
  16. Android onActivityResult和setResult
  17. 20165203实验四 Andriod程序设计
  18. struct pollfd
  19. 验证是否是正整数,是否是mail,是否是正确的身份证
  20. HBASE+Solr实现详单查询--转

热门文章

  1. IBM服务器的2种IMM和1种raid管理方式
  2. ADT 更新遇到的一个BUG解决方案【转】
  3. wake on lan sender 2.0.8
  4. laravel常用集合的使用
  5. 前后端API交互数据加密——AES与RSA混合加密完整实例(转载)
  6. 多线程事务回滚sqlSession, spring-mybatis 开启事务
  7. openstack 私有云
  8. CF513F2 题解
  9. imputation-文献:False signals induced by single-cell imputation(scRNA-seq插补引入的假阳性问题)
  10. 用深度学习模型Word2Vec探索《红楼梦》人物关系