Python画出心目中的自己
作者 | 李秋键
责编 | 晋兆雨
头图 | CSDN下载自视觉中国
引言:人脸图像的生成在各个行业有着重要应用,例如刑事调查、人物设计、教育培训等。然而一幅逼真的人脸肖像,对于职业画家也要至少数小时才能绘制出来;对于从未接触过绘画的新手,就更是难如登天了。新手绘制出来的人脸草图往往非常简陋抽象,甚至有不匀称、不完整。但如果使用智能人脸画板,无疑是有如神助。
本项目主要来源于中科院和香港城市大学的一项研究DeepFaceDrawing,论文标题是《DeepFaceDrawing: DeepGeneration of Face Images from Sketches》
具体效果如下图可见:
实验前的准备
首先我们使用的python版本是3.6.5所用到的模块如下:
Pyqt5模块:PyQt5是基于Digia公司强大的图形程式框架Qt5的python接口,由一组python模块构成。PyQt5本身拥有超过620个类和6000函数及方法。在可以运行于多个平台,包括:Unix, Windows, and Mac OS。
opencv是将用来进行图像处理和生成。
numpy模块用来处理矩阵运算。
Jittor模块国内清华大学开源的深度学习框架。
_thread是多线程库。
网络模型的定义和训练
首先这个图像合成模块采用了一种利用发生器和鉴别器的GAN结构。从融合的特征图生成真实的人脸图像。鉴别器采用多尺度鉴别方式:对输入进行尺度划分,特征图和生成的图像在三个不同的层次上,经过三个不同的过程。:
(1)权重网络层和损失定义:
def weights_init_normal(m):classname = m.__class__.__name__ifclassname.find("Conv") != -1:jt.init.gauss_(m.weight,0.0, 0.02)elifclassname.find("BatchNorm") != -1:jt.init.gauss_(m.weight,1.0, 0.02)jt.init.constant_(m.bias,0.0)def get_norm_layer(norm_type='instance'):if (norm_type == 'batch'):norm_layer = nn.BatchNormelif (norm_type == 'instance'):norm_layer =nn.InstanceNorm2delse:raiseNotImplementedError(('normalization layer [%s] is not found' % norm_type))return norm_layerclass MSELoss:def __init__(self):passdef __call__(self, output,target):from jittor.nn importmse_lossreturn mse_loss(output,target)class BCELoss:def __init__(self):passdef __call__(self, output,target):from jittor.nn importbce_lossreturn bce_loss(output,target)
(2)模型特征编解码:
特征匹配模块包含5个译码网络,以compact作为输入由分量流形得到的特征向量,并将其转换为对应的特征向量为后续生成的特征图的大小。
def define_part_encoder(model='mouth', norm='instance', input_nc=1,latent_dim=512):norm_layer =get_norm_layer(norm_type=norm)image_size = 512if 'eye' in model:image_size = 128elif 'mouth' in model:image_size = 192elif 'nose' in model:image_size = 160elif 'face' in model:image_size = 512else:print("Whole Image!!")net_encoder =EncoderGenerator_Res(norm_layer,image_size,input_nc, latent_dim) # input longsize 256 to 512*4*4 print("net_encoder of part"+model+" is:",image_size)return net_encoderdef define_part_decoder(model='mouth', norm='instance', output_nc=1,latent_dim=512):norm_layer =get_norm_layer(norm_type=norm)image_size = 512if 'eye' in model:image_size = 128elif 'mouth' in model:image_size = 192elif 'nose' in model:image_size = 160else:print("Whole Image!!")net_decoder =DecoderGenerator_image_Res(norm_layer,image_size,output_nc, latent_dim) # input longsize 256 to 512*4*4print("net_decoder to imageof part "+model+" is:",image_size)return net_decoderdef define_feature_decoder(model='mouth', norm='instance', output_nc=1,latent_dim=512):norm_layer =get_norm_layer(norm_type=norm)image_size = 512if 'eye' in model:image_size = 128elif 'mouth' in model:image_size = 192elif 'nose' in model:image_size = 160else:print("Whole Image!!")net_decoder =DecoderGenerator_feature_Res(norm_layer,image_size,output_nc, latent_dim) # input longsize 256 to 512*4*4print("net_decoder to imageof part "+model+" is:",image_size)# print(net_decoder)return net_decoderdef define_G(input_nc, output_nc, ngf, n_downsample_global=3,n_blocks_global=9, norm='instance'):norm_layer =get_norm_layer(norm_type=norm) netG = GlobalGenerator(input_nc,output_nc, ngf, n_downsample_global, n_blocks_global, norm_layer)return netG
图形界面的定义
在这篇论文中,作者一方面将人脸关键区域(双眼、鼻、嘴和其他区域)作为面元,学习其特征嵌入,将输入草图的对应部分送到由数据库样本中面元的特征向量构成的流形空间进行校准。另一方面,参考 pix2pixHD [5]的网络模型设计,使用 conditional GAN 来学习从编码的面元特征到真实图像的映射生成结果。
(1)鼠标绘制函数的定义:
class OutputGraphicsScene(QGraphicsScene):def __init__(self, parent=None):QGraphicsScene.__init__(self, parent)# self.modes = mode_listself.mouse_clicked = Falseself.prev_pt = Noneself.setSceneRect(0,0,self.width(),self.height())# self.masked_image = Noneself.selectMode = 0# save the history of editself.history = []self.ori_img = np.ones((512,512, 3),dtype=np.uint8)*255self.mask_put = 1 # 1 marksuse brush while 0 user eraseself.convert = False# self.setPos(0 ,0)self.firstDisplay = Trueself.convert_on = Falsedef reset(self):self.convert = Falseself.ori_img = np.ones((512,512, 3),dtype=np.uint8)*255self.updatePixmap(True)self.prev_pt = Nonedef setSketchImag(self,sketch_mat, mouse_up=False):self.ori_img =sketch_mat.copy()self.image_list = []self.image_list.append(self.ori_img.copy() )def mousePressEvent(self,event):if not self.mask_put orself.selectMode == 1:self.mouse_clicked =Trueself.prev_pt = Noneelse:self.make_sketch(event.scenePos())def make_sketch_Eraser(self,pts):if len(pts)>0:for pt in pts:cv2.line(self.color_img,pt['prev'],pt['curr'],self.paint_color,self.paint_size)cv2.line(self.mask_img,pt['prev'],pt['curr'],(0,0,0),self.paint_size )self.updatePixmap()def modify_sketch(self, pts):if len(pts)>0:for pt in pts:cv2.line(self.ori_img,pt['prev'],pt['curr'],self.paint_color,self.paint_size)self.updatePixmap()def get_stk_color(self, color):self.stk_color = colordef erase_prev_pt(self):self.prev_pt = Nonedef reset_items(self):for i inrange(len(self.items())):item = self.items()[0]self.removeItem(item)def undo(self):iflen(self.image_list)>1:num =len(self.image_list)-2self.ori_img =self.image_list[num].copy()self.image_list.pop(num+1)self.updatePixmap(True)def getImage(self):returnself.ori_img*(1-self.mask_img) +self.color_img*self.mask_imgdefupdatePixmap(self,mouse_up=False):sketch = self.ori_imgqim = QImage(sketch.data,sketch.shape[1], sketch.shape[0], QImage.Format_RGB888)if self.firstDisplay :self.reset_items()self.imItem =self.addPixmap(QPixmap.fromImage(qim))self.firstDispla = Falseelse:self.imItem.setPixmap(QPixmap.fromImage(qim))def fresh_board(self):print('======================================================')while(True):if(self.convert_on):print('======================================================')time.sleep(100)iter_start_time =time.time()self.updatePixmap()print('TimeSketch:',time.time() - iter_start_time)
(2)GUI界面:其核心思路并非直接用输入草图作为网络生成条件,而是将人脸进行分块操作后利用数据驱动的思想对抽象的草图特征空间进行隐式建模,并在这个流形空间中找到输入草图特征的近邻组合来重构特征,进而合成人脸图像。
class WindowUI(QtWidgets.QMainWindow,Ui_SketchGUI):def __init__(self):super(WindowUI,self).__init__()self.setupUi(self)self.setEvents()self._translate =QtCore.QCoreApplication.translateself.output_img = Noneself.brush_size =self.BrushSize.value()self.eraser_size =self.EraseSize.value()self.modes = [0,1,0] #0marks the eraser, 1 marks the brushself.Modify_modes = [0,1,0]#0 marks the eraser, 1 marks the brushself.output_scene =OutputGraphicsScene()self.output.setScene(self.output_scene)self.output.setAlignment(Qt.AlignTop | Qt.AlignLeft)self.output.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)self.output.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)self.output_view =QGraphicsView(self.output_scene)#self.output_view.fitInView(self.output_scene.updatePixmap())self.input_scene =InputGraphicsScene(self.modes, self.brush_size,self.output_scene)self.input.setScene(self.input_scene)self.input.setAlignment(Qt.AlignTop | Qt.AlignLeft)self.input.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)self.input.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)self.input_scene.convert_on= self.RealTime_checkBox.isChecked()self.output_scene.convert_on= self.RealTime_checkBox.isChecked()self.BrushNum_label.setText(self._translate("SketchGUI",str(self.brush_size)))self.EraserNum_label.setText(self._translate("SketchGUI",str(self.eraser_size)))self.start_time =time.time()# self.# try:# # thread.start_new_thread(self.output_scene.fresh_board,())# thread.start_new_thread(self.input_scene.thread_shadow,())# except:# print("Error: unable to startthread")# print("Finish")def setEvents(self):self.Undo_Button.clicked.connect(self.undo)self.Brush_Button.clicked.connect(self.brush_mode)self.BrushSize.valueChanged.connect(self.brush_change)self.Clear_Button.clicked.connect(self.clear)self.Eraser_Button.clicked.connect(self.eraser_mode)self.EraseSize.valueChanged.connect(self.eraser_change)self.Save_Button.clicked.connect(self.saveFile)#weight barself.part0_Slider.valueChanged.connect(self.changePart)self.part1_Slider.valueChanged.connect(self.changePart)self.part2_Slider.valueChanged.connect(self.changePart)self.part3_Slider.valueChanged.connect(self.changePart)self.part4_Slider.valueChanged.connect(self.changePart)self.part5_Slider.valueChanged.connect(self.changAllPart)self.Load_Button.clicked.connect(self.open)self.Convert_Sketch.clicked.connect(self.convert)self.RealTime_checkBox.clicked.connect(self.convert_on)self.Shadow_checkBox.clicked.connect(self.shadow_on)self.Female_Button.clicked.connect(self.choose_Gender)self.Man_Button.clicked.connect(self.choose_Gender)self.actionSave.triggered.connect(self.saveFile)def mode_select(self, mode):for i inrange(len(self.modes)):self.modes[i] = 0self.modes[mode] = 1def brush_mode(self):self.mode_select(1)self.brush_change()self.statusBar().showMessage("Brush")def eraser_mode(self):self.mode_select(0)self.eraser_change()self.statusBar().showMessage("Eraser")def undo(self):self.input_scene.undo()self.output_scene.undo()def brush_change(self):self.brush_size =self.BrushSize.value()self.BrushNum_label.setText(self._translate("SketchGUI",str(self.brush_size)))if self.modes[1]:self.input_scene.paint_size = self.brush_sizeself.input_scene.paint_color = (0,0,0)self.statusBar().showMessage("Change Brush Size in ",self.brush_size)def eraser_change(self):self.eraser_size =self.EraseSize.value()self.EraserNum_label.setText(self._translate("SketchGUI",str(self.eraser_size)))if self.modes[0]:print( self.eraser_size)self.input_scene.paint_size = self.eraser_sizeself.input_scene.paint_color = (1,1,1)self.statusBar().showMessage("Change Eraser Size in ",self.eraser_size)def changePart(self):self.input_scene.part_weight['eye1'] = self.part0_Slider.value()/100self.input_scene.part_weight['eye2']= self.part1_Slider.value()/100self.input_scene.part_weight['nose'] = self.part2_Slider.value()/100self.input_scene.part_weight['mouth'] = self.part3_Slider.value()/100self.input_scene.part_weight[''] = self.part4_Slider.value()/100self.input_scene.start_Shadow()#self.input_scene.updatePixmap()def changAllPart(self):value =self.part5_Slider.value()self.part0_Slider.setProperty("value", value)self.part1_Slider.setProperty("value", value)self.part2_Slider.setProperty("value", value)self.part3_Slider.setProperty("value", value)self.part4_Slider.setProperty("value", value)self.changePart()def clear(self):self.input_scene.reset()self.output_scene.reset()self.start_time =time.time()self.input_scene.start_Shadow()self.statusBar().showMessage("Clear Drawing Board")def convert(self):self.statusBar().showMessage("Press Convert")self.input_scene.convert_RGB()self.output_scene.updatePixmap()def open(self):fileName, _ =QFileDialog.getOpenFileName(self, "Open File",QDir.currentPath(),"Images Files (*.*)") #jpg;*.jpeg;*.pngif fileName:image =QPixmap(fileName)mat_img =cv2.imread(fileName)mat_img = cv2.resize(mat_img,(512, 512), interpolation=cv2.INTER_CUBIC)mat_img =cv2.cvtColor(mat_img, cv2.COLOR_RGB2BGR)if image.isNull():QMessageBox.information(self, "Image Viewer","Cannotload %s." % fileName)return#cv2.imshow('open',mat_img)self.input_scene.start_Shadow()self.input_scene.setSketchImag(mat_img)def saveFile(self):cur_time =strftime("%Y-%m-%d-%H-%M-%S", gmtime())file_dir ='./saveImage/'+cur_timeif notos.path.isdir(file_dir) :os.makedirs(file_dir)cv2.imwrite(file_dir+'/hand-draw.jpg',self.input_scene.sketch_img*255)cv2.imwrite(file_dir+'/colorized.jpg',cv2.cvtColor(self.output_scene.ori_img,cv2.COLOR_BGR2RGB))print(file_dir)def convert_on(self):# ifself.RealTime_checkBox.isCheched():print('self.RealTime_checkBox',self.input_scene.convert_on)self.input_scene.convert_on= self.RealTime_checkBox.isChecked()self.output_scene.convert_on= self.RealTime_checkBox.isChecked()def shadow_on(self):_translate =QtCore.QCoreApplication.translateself.input_scene.shadow_on =not self.input_scene.shadow_onself.input_scene.updatePixmap()ifself.input_scene.shadow_on:self.statusBar().showMessage("Shadow ON")else:self.statusBar().showMessage("Shadow OFF")def choose_Gender(self):ifself.Female_Button.isChecked():self.input_scene.sex = 1else:self.input_scene.sex = 0self.input_scene.start_Shadow()
总结
这里给出模型的体验网址:
http://www.geometrylearning.com:3000/index_621.html
该方法核心亮点之一,便是以多通道特征图作为中间结果来改善信息流。从本质上看,这是将输入草图作为软约束来替代传统方法中的硬约束,因此能够用粗糙甚至不完整的草图来生成高质量的完整人脸图像。
反思DeepFaceDrawing
1)画不出丑脸:
从图中可以看出,即使给出丑陋的草图,输出的也会是平均来说漂亮的人脸,这大概是因为所用的训练数据集都是名人,平均“颜值”较高,因此神经网络学到了一种漂亮的平均;这能算是一种在“颜值上的”数据不平衡问题吗。
2)安全问题
比如人脸支付场景中,可能存在利用该项技术盗刷的问题。随着人脸活体检测技术的发展,这种隐患应该能得以有效避免。
3)技术攻击性
相比于Deepfake,本文的DeepFaceDrawing应该算是相对无害的。
4)商业价值
如论文作者所说,这项技术在犯罪侦查、人物设计、教育培训等方面都可以有所作为。期待有一天这项技术更加通用,这样一来其商业价值会更大。
完整代码:
链接:https://pan.baidu.com/s/1ARIzPEbUSNzAIdPsRl6h-A
提取码:4llk
作者简介
李秋键,CSDN 博客专家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap安卓武侠游戏一部,vip视频解析,文意转换工具,写作机器人等项目,发表论文若干,多次高数竞赛获奖等等。
更多精彩推荐
清华、北大教授同台激辩:脑科学是否真的能启发AI?
用Python分析5000+抖音大V,粉丝最喜欢的视频类型是它
看清头秃元凶,腾讯AI首度揭示真相
PHP 还有未来么,还是 25 岁就“寿终正寝”了?
相关文章:

认识 PHP 的hash函数
Hashing function (散列函式) 在网页应用中被广泛采用,从数码签署、错误检测、登入验证、到压缩储存空间,由于它的原理比较复杂,很多人把它跟加密函式混淆,对于如何运用hash function,如何选择合适的hash function&…

const在函数前与函数后的区别 [转]
[转] http://blog.csdn.net/clozxy/article/details/5679887 一 const基础 如果const关键字不涉及到指针,我们很好理解,下面是涉及到指针的情况: int b 500; const int* a &b; [1] int const …

《HTML5游戏编程核心技术与实战》——2.8 小结
本节书摘来自异步社区《HTML5游戏编程核心技术与实战》一书中的第2章,第2.8节,作者: 向峰 更多章节内容可以访问云栖社区“异步社区”公众号查看。 2.8 小结 本章介绍了canvas的一些常用的操作,作为HTML5的最重要的特性,canvas使得…

IANA保留地址
IANA 就是指(Internet Assigned Numbers Authority) ,Internet号分配机构。负责对IP地址分配规划以及对TCP/UDP公共服务的端口定义。国际互联网代理成员管理局(IANA)是在国际互联网中使用的IP 地址、域名和许多其它参数的管理机构。IP地址、自…

张亚勤世界互联网大会谈AI:将变革传统行业,催生新业态
11月23日至24日,一年一度的世界互联网大会互联网发展论坛如期召开。全球疫情冲击下,科技创新成为了海内外共同关注的焦点。其中,人工智能作为新一轮科技革命和产业变革的重要驱动力量,同样饱受关注。 在24日上午的"人工智能…

如何通过参数来切换图表和数据
在报表设计的过程中有时候我们想在一张报表中既可以看到数据又可以看到图表,但是如果把数据和图表放在同一页面中似乎不太美观,所以我们可以用参数来控制是要显示数据还是显示图表。下面来看看如何实现通过参数来切换图表和数据 设计一张既有数据又有图表…

安装 Fedora 22 后要做的事情
Red Hat操作系统的社区开发版的最新成员Fedora 22,已经于2015年5月26日发布了。对这个经典的Fedora发行版的发布充斥着各种猜测和预期,而最终Fedora 22推出了许多重大变化。 就初始化进程而言,Systemd还是个新生儿,但它已经准备好…

针对《评人工智能如何走向新阶段》一文,继续发布国内外的跟贴留言第二部552-556条
552. 无人驾驶与自动驾驶 无人驾驶与自动驾驶技术属于人工智能技术范畴,近年来有长足进步。无人驾驶与自动驾驶的实现的与路况密切有关。 根据国际自动机工程师学会2004年制度的“无人驾驶与自动驾驶技术界定标准”,将路况分成5级: 根据美国…

Web的桌面提醒(Popup)
大多数Windows程序都有桌面提醒(Popup)功能,如Msn Messenger,Outlook2003,FoxMail,SharpReader等,对用户来说可以非常的方便最新的信息。 在Web中借用IE5.5的Popup,也可以实现类似的…

linux的裁剪过程,让你的小linux更加完善,赶快试试吧!
一、系统启动流程: 1、POST-->BIOS(Boot Sequence)--> BootLoader(MBR)--> Kernel(initrd,initramfs)--> init (/etc/inittab) 第一步首先加电自检,计算机本身不会执行程序,由此它会…

《Adobe Premiere Pro CC经典教程(彩色版)》——2.2 建立项目
本节书摘来自异步社区《Adobe Premiere Pro CC经典教程(彩色版)》一书中的第2课,第2.2节,作者 【英国】Maxim Jago(马克西姆 亚戈),译者 陈昕昕,郭光伟 ,更多章节内容可以…

针对《评人工智能如何走向新阶段》一文,继续发布国内外的跟贴留言第二部557-561条如下
557,解决最后一公里短板,提升语义网络内涵,使之具有实现可解释人工智能(或实现认知智能)的能力,尚待努力! 在跟贴263、521中,谈到提升语义网络内涵的解决之道,要坚持数据…

struts2+hibernate+Spring分层开发
web.xml中要加Spring的listener,struts2的filter的配置。UI struts2: jsp struts.xml ActionSpring ActionSpring:applicationContent-actions.xml Service Spring:applicationContent-services.xml DAO Entity DAL hibernate: …

DataGrid鼠标事件处理
http://blog.csdn.net/bgu/完成功能是DataGrid的页面选中事件、鼠标事件、双击事件改变TR的色彩。代码很简单,只是一点JS操作。JS文件:GridControl.js/*------------ DataGrid鼠标事件处理 ------------功能:用于数据梆定后鼠标事件参数说明:obj:对像thisfontColor:…

《精通 ASP.NET MVC 3 框架(第三版)》----第2章 准备工作 2.1 准备工作站
本节书摘来自异步社区《精通 ASP.NET MVC 3 框架(第三版)》一书中的第2章,第1节,作者: 【美】Adam Freeman , Steven Standerson,译者: 林逸 , 李萍 , 更多章节内容可以访问云栖社区…

DataGrid鼠标事件方法
http://blog.csdn.net/bgu/ JS文件源码:GridColorControl.js/*-----------------调用说明-----------------说明:可用于架设页面事件。入口函数:OnFocusSet(....)如:OnFocusSet( "#000000","#FFFFFF","#…
张亚勤谈数字化3.0:由物理与生物世界的数字化构成 | WIC
11月23日至24日,一年一度的世界互联网大会互联网发展论坛如期召开。全球疫情冲击下,科技创新成为了海内外共同关注的焦点。其中,人工智能作为新一轮科技革命和产业变革的重要驱动力量,同样饱受关注。在24日上午的“人工智能&#…

print_r() 'ThinkPHP\Common\common.php 601
Fatal error: print_r() [<a hrefref.outcontrol>ref.outcontrol</a>]: Cannot use output buffering in output buffering display handlers in D:\www\bjydf\ThinkPHP\Common\common.php on line 601 在thinkphp中用phpexcel导出数据错误<b>Fatal error<…

《Android传感器开发与智能设备案例实战》——导读
本节书摘来自异步社区《Android传感器开发与智能设备案例实战》一书中的目录,作者 朱元波,更多章节内容可以访问云栖社区“异步社区”公众号查看 目 录前 言 第1章 Android开发技术基础 第1章第1.1节智能手机操作系统介绍第1章第1.2节Android的巨大优势[…

详解基于busybox、dropbear、ngnix制作完整的嵌入式Linux系统
说明: 《一》:查看此博文,建议查看笔者上一篇博文(Linux启动过程),因为只有在完全了解Linux系统启动流程及一些配置文件的相关性,在阅读此博文才能有思路,理解起来更容易写。 《二》:此…
CSDN湘苗培优,打造高素质技术人才
前言2020年长沙发出软件再出发号召,同时发布了《长沙市软件和信息技术服务业发展三年(2020-2022 年)行动计划》。当软件产业的生态逐渐建立,企业孵化培育的土壤逐渐肥沃,长沙软件产业焕发出前所未有的活力和生机,一大批软件产业项…

在ASP.NET 中实现单点登录
出自:【孟宪会之精彩世界】 发布日期:2005年1月27日 8点48分0秒 [有删改] 由于某些原因,在我们的应用中会遇到一个用户只能在一个地方登录的情况,也就是我们通常所说的单点登录。在ASP.NET中实现单点登录其实很简单,下…

《Unity着色器和屏幕特效》——2.2 进阶的透明效果
本节书摘来自华章计算机《Unity着色器和屏幕特效》一书中的第2章,第2.2节,作者[美]杰米迪恩(Jamie Dean),译 周翀,张薇,更多章节内容可以访问云栖社区“华章计算机”公众…
机器模拟共情,情感AI正踏足诸多行业
作者 | 平凡来源 | CSDN作者简介:平凡,诺桑比亚大学计算机科学博士情感AI是一个跨学科领域,涉及计算机科学、 心理学和认知科学,旨在研发能够识别、解释、处理、模拟人类情感的系统。[虽然该学科最早可追溯至早期的哲学研究&#…

SQL Server 中各个系统表的作用
sysaltfiles 主数据库 保存数据库的文件syscharsets 主数据库 字符集与排序顺序sysconfigures 主数据库 配置选项syscurconfigs 主数据库 当前配置选项sysdatabases 主数据库 服务器中的数据…

“批判”按劳取酬
“批判”按劳取酬<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />Jack zhai按劳取酬的意思就是付出多少劳动,就获得多少报酬;这曾经是我认为最为合理的老板与员工之间的合约关系。然而近几年,…

《编译与反编译技术实战 》一2.3 编译器的设计与实现概述
本节书摘来自华章出版社《编译与反编译技术实战 》一书中的第2章,第2.3节,庞建民 主编 ,刘晓楠 陶红伟 岳 峰 戴超 编著,更多章节内容可以访问云栖社区“华章计算机”公众号查看。 2.3 编译器的设计与实现概述 根据不同的用…
U^2-Net跨界肖像画,完美复刻人物细节,GitHub标星2.5K+
来源 | Jack Cui头图 | CSDN下载自视觉中国今年提出的 U^2-Net 显著性检测算法,刷爆了 reddit 和 twitter,号称是 2020 年「地表最强」的静态背景分割算法,可以看下效果:你以为今天要讲分割?错!U^2-Net 这两…

使用sourceInsight 提高代码编写效率
source Insight是一个强大的程序编写器和代码浏览器,它拥有内置的对C/C,C#和Java等程序的分析。本文总结了常用的快捷键,重要的宏的应用(可以多行注释,自动补全,自动生成头文件和函数说明,修改说明……&…

php几个预定义变量$_SERVER['DOCUMENT_ROOT']
<?php echo documentroot:.$_SERVER[DOCUMENT_ROOT].<br>; //根目录,在apache的配置文件里定义:httpd.conf 比如:DocumentRoot "D:/work/php_root" echo httphost:.$_SERVER[HTTP_HOST].<br>; //域名,比如&#…