偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

國(guó)外程序員真會(huì)玩,他用這個(gè)技術(shù)整蠱了全公司的人…

譯文
新聞 移動(dòng)開(kāi)發(fā)
我喜歡用Photoshop修改各種東西,再把結(jié)果在Slack公司內(nèi)發(fā)布,每次都能帶來(lái)新的想法我享受在其中。不過(guò)重復(fù)打開(kāi)Photoshop再?gòu)?fù)制/粘貼面部圖像確實(shí)相當(dāng)乏味。

【51CTO.com快譯】我喜歡用Photoshop修改各種東西,再把結(jié)果在Slack公司內(nèi)發(fā)布,每次都能帶來(lái)新的想法我享受在其中。

不過(guò)重復(fù)打開(kāi)Photoshop再?gòu)?fù)制/粘貼面部圖像確實(shí)相當(dāng)乏味。

程序員

[[185213]]

在最初產(chǎn)生這個(gè)想法時(shí),我就意識(shí)到這個(gè)項(xiàng)目將主要包含三大組成部分:

1. 簡(jiǎn)單圖像修改

2. Slack集成

3. 面部檢測(cè)

以往我曾經(jīng)使用過(guò)Go中的image與image/draw軟件包,并閱讀過(guò)與之相關(guān)的幾篇文章,因此我對(duì)于完成這項(xiàng)任務(wù)很有信心。組成部分1就此搞定。

我還曾經(jīng)在Go中構(gòu)建過(guò)一款玩具性質(zhì)的Slack機(jī)器人,其中用到了查找自谷歌的幾條指令。雖然缺少Go Slack官方整體客戶端會(huì)讓問(wèn)題變得更為復(fù)雜,但出于最基本的需求,我相信自己能夠完成通過(guò)Slack下載及上傳圖像這樣一項(xiàng)工作。組成部分2也就不是問(wèn)題了。

我唯一不確定的是面部檢測(cè)工作到底是否易于實(shí)現(xiàn)。我在谷歌上查找golang面部檢測(cè)內(nèi)容,并點(diǎn)開(kāi)***條結(jié)果,其內(nèi)容指向StackOverflow上關(guān)于go-opencv計(jì)算機(jī)視覺(jué)庫(kù)的一條問(wèn)題。在查閱了該庫(kù)中的面部檢測(cè)示例項(xiàng)目后,我了解到了自己需要掌握的一切。組成部分3也同樣得到了解決。

面部檢測(cè)

由于熟悉度***,所以我決定首先從面部檢測(cè)入手。這是項(xiàng)目中***的難題,因此我打算先看看自己能否搞定,如果不行那其它的工作都將毫無(wú)意義。

我決定盡可能對(duì)go-opencv庫(kù)進(jìn)行封裝??梢钥隙ǖ氖牵琽pencv數(shù)據(jù)類(lèi)型與Go標(biāo)準(zhǔn)庫(kù)有所區(qū)別,至少在其定義Image與Rectangle兩項(xiàng)接口方面存在差異,因此必須作出一些調(diào)整。

我在其中發(fā)現(xiàn)一項(xiàng)對(duì)opencv.FromImage方法的引用,其負(fù)責(zé)將Go的image.Image轉(zhuǎn)換為opencv庫(kù)的形式。這意味著我不再需要將文件路徑傳遞至opencv.LoadImage方法以進(jìn)行轉(zhuǎn)換,而可以直接處理存儲(chǔ)在內(nèi)存中的鏡像。這能夠節(jié)約從Slack接收?qǐng)D像后將其保存在文件系統(tǒng)中的步驟。

遺憾的是,我無(wú)法利用同樣的轉(zhuǎn)換方式加載Haar面部識(shí)別XML文件,不過(guò)這樣的結(jié)果我還可以接受,所以暫時(shí)先這樣吧。

以此為基礎(chǔ),我編寫(xiě)出了以下facefinder包:

  1. package facefinder import ( "image""github.com/lazywei/go-opencv/opencv" ) var faceCascade *opencv.HaarCascade type Finder struct { cascade *opencv.HaarCascade } func NewFinder(xml string) *Finder { return &Finder{ cascade: opencv.LoadHaarClassifierCascade(xml), } } func (f *Finder) Detect(i image.Image) []image.Rectangle { var output []image.Rectangle faces :f.cascade.DetectObjects(opencv.FromImage(i)) for _, face :range faces { output = append(output, image.Rectangle{ image.Point{face.X(), face.Y()}, image.Point{face.X() + face.Width(), face.Y() + face.Height()}, }) } return output } 

而后,我能夠輕松找到圖像中的面部區(qū)域:

  1. imageReader, _ :os.Open(imageFile) baseImage, _, _ :image.Decode(imageReader) finder :facefinder.NewFinder(haarCascadeFilepath) faces :finder.Detect(baseImage) for _, face :range faces { // [...] } 

我從谷歌上復(fù)制了幾段“繪制矩形”代碼以進(jìn)行功能檢查,并確定以上代碼確實(shí)能夠正常工作。有了位置信息,我又鼓搗出一條圖像加載轉(zhuǎn)換函數(shù)(其中更關(guān)注錯(cuò)誤內(nèi)容,而非急于將一切塞進(jìn))。

  1. func loadImage(file string) image.Image { reader, err :os.Open(file) if err != nil { log.Fatalf("error loading %s: %s", file, err) } img, _, err :image.Decode(reader) if err != nil { log.Fatalf("error loading %s: %s", file, err) } return img } 

圖像修改

接下來(lái),我的新循環(huán)如下所示:

  1. baseImage :loadImage(imageFile) chrisFace :loadImage(chrisFaceFile) bounds :baseImage.Bounds() finder :facefinder.NewFinder(haarCascadeFilepath) faces :finder.Detect(baseImage) // Convert image.Image to a mutable image.ImageRGBA canvas :image.NewRGBA(bounds) draw.Draw(canvas, bounds, baseImage, bounds.Min, draw.Src) for _, face :range faces { draw.Draw( canvas, face, chrisFace, bounds.Min, draw.Src, ) } 

令人振奮,測(cè)試結(jié)果一切順利。

[[185214]]

言歸正傳,其***實(shí)際效果就遠(yuǎn)超我的預(yù)期。矩形繪制算法真棒!

在圖像修改方面,我首先得想辦法去掉黑色背景。我以前曾使用過(guò)PNG配合透明背景的方法,因此確信其一定有效。在谷歌了幾下后,我偶然發(fā)現(xiàn)了draw.Draw函數(shù)中的draw.Over。我將其塞進(jìn)正在使用的draw.Src,確實(shí)有效!

[[185215]]

雖然也可以用羽毛筆慢慢繪邊,但腦袋里的一個(gè)聲音告訴我,差不多就可以了。

好的,接下來(lái)我需要把面部圖像縮小一點(diǎn)??梢钥隙ǖ氖牵绻麑⒚娌繄D像放進(jìn)尺寸完全相同的矩形,那么二者肯定無(wú)法匹配。這只是一款面部檢測(cè)工具,而非頭部檢測(cè)工具,這意味著我獲得的矩形并不適用于替換整個(gè)頭部。我編寫(xiě)了一條快速函數(shù)以為image.Rectangle增加特定空白邊緣,最終將具體值設(shè)定為30%。

完成后,我開(kāi)始對(duì)圖像進(jìn)行大小/匹配調(diào)整。最終,我選擇了disintegration/imaging,其擁有一條簡(jiǎn)單的imaging.Fit函數(shù)且提供水平鏡像等其它轉(zhuǎn)換操作。我的面部源圖像不多,所以我想這種鏡像功能可以提供多一種圖像選擇。

在導(dǎo)入后,我的新循環(huán)如下所示:

  1. for _, face :range faces { // Pad the rectangle by 30 percent rect :rectMargin(30.0, face) // Grab a random face (also 50/50 chance it's mirrored) newFace :chrisFaces.Random() chrisFace :imaging.Fit(newFace, rect.Dx(), rect.Dy(), imaging.Lanczos) draw.Draw( canvas, rect, chrisFace, bounds.Min, draw.Over, ) } 

我又進(jìn)行了一輪新的測(cè)試,效果相當(dāng)不錯(cuò)!

[[185216]]

[[185217]]

到這里,我意識(shí)到自己做出了一些真正有價(jià)值的東西。

Slack集成

我把面部修改代碼轉(zhuǎn)化為一個(gè)可運(yùn)行的二進(jìn)制文件,并打算將其打包成一個(gè)Slack機(jī)器人。之所以先轉(zhuǎn)換為二進(jìn)制形式,是為了方便測(cè)試并在確定一切無(wú)誤后再行打包?,F(xiàn)在時(shí)機(jī)已經(jīng)成熟,我將把它變成Slack機(jī)器人。

當(dāng)然,由于個(gè)人水平的限制,我又轉(zhuǎn)向了谷歌。

***條結(jié)果就是我所需要的內(nèi)容。我花了大量時(shí)間閱讀Slack的API說(shuō)明文檔并加以實(shí)踐,最終我得到了以下結(jié)果:

程序員

不錯(cuò)

***套迭代使用了Slack上傳,但其作為自由Slack層意味著其不夠理想。我轉(zhuǎn)而將輸出結(jié)果以本地方式存儲(chǔ)在自己的服務(wù)器上,而后再將其鏈至Slack。由于Slack會(huì)自動(dòng)擴(kuò)展大部分圖像鏈接,因此這種作法對(duì)大多數(shù)人來(lái)說(shuō)并不會(huì)影響到用戶體驗(yàn),也不會(huì)引來(lái)頂頭上司的注意。

由于訪問(wèn)過(guò)程更為輕松,現(xiàn)在我能夠快速獲得大量實(shí)驗(yàn)性面部圖像。我意識(shí)到,如果其找不到任何面部圖像,則會(huì)全程回復(fù)同樣的原有圖像——這就不好玩了。所以我將循環(huán)調(diào)整為:

  1. iflen(faces) == 0 { // Grab a specific face and resize it to 1/3 the width// of the base image face :imaging.Resize( chrisFaces[0], bounds.Dx()/3, 0, imaging.Lanczos, ) face_bounds :face.Bounds() draw.Draw( canvas, bounds, face, // I'll be honest, I was a couple beers in when I came up with this and I// have no idea how it works exactly, but it puts the face at the bottom of// the image, centered horizontally with the lower half of the face cut off bounds.Min.Add(image.Pt( -bounds.Max/2+face_bounds.Max.X/2, -bounds.Max.Y+int(float64(face_bounds.Max.Y)/1.9), )), draw.Over, ) } 

現(xiàn)在的結(jié)果是:

[[185218]]

我個(gè)人對(duì)這套解決方案非常滿意。

到這里全部工作已經(jīng)就緒,就等同事們的反應(yīng)了。我只用了一個(gè)晚上就完全了從概念到原型的全部工作,沒(méi)人知道我為他們準(zhǔn)備了怎樣的驚喜。

程序員

截至目前,我的經(jīng)理是最為積極的Chrisbot手動(dòng)配置用戶。

程序員

抱歉了Mat,看來(lái)自動(dòng)化方案最終一定會(huì)取代人類(lèi)的職位。

[[185219]]

但這家伙自己則非常開(kāi)心。

不久之后,整個(gè)辦公室都在向@Chrisbot發(fā)送圖片。

我驚喜地發(fā)現(xiàn),它確實(shí)能夠正確地處理面部重疊情況,即首先繪制最遠(yuǎn)處的面孔。雖然這純粹屬于go-opencv庫(kù)返回矩形時(shí)實(shí)際順序帶來(lái)的副作用,但我對(duì)結(jié)果非常滿意。

不過(guò)雖然自動(dòng)化面部替換大大增加了Slack當(dāng)中Chris的亮相次數(shù),但仍有一些人認(rèn)為,人為操作的結(jié)果更有靈性一些。

不得不承認(rèn),他們的觀點(diǎn)確實(shí)站得住腳——至少在某些情況之下。

程序員

【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com】

責(zé)任編輯:陳琳 來(lái)源: 51cto
相關(guān)推薦

2019-04-26 13:26:00

預(yù)測(cè)股票深度學(xué)習(xí)股票

2020-09-25 15:43:25

程序員網(wǎng)站技術(shù)

2021-02-15 16:30:35

AI人工智能人臉識(shí)別

2012-11-22 14:00:26

程序員

2020-10-12 08:45:25

程序員技術(shù)開(kāi)發(fā)

2011-06-11 20:59:12

程序員

2016-11-29 07:53:57

科技新聞早報(bào)計(jì)算機(jī)

2020-05-08 10:28:29

Node.js程序員JavaScript

2017-01-17 12:15:14

互聯(lián)網(wǎng) 機(jī)器

2018-06-14 09:59:48

程序員代碼大公司

2012-06-27 09:29:49

程序員

2009-03-13 10:27:25

女程序員天才人生

2017-06-12 11:14:52

程序員技術(shù)停滯

2012-07-20 11:16:26

程序員

2015-09-02 13:19:55

微軟Cortana

2020-10-28 09:43:40

前端開(kāi)發(fā)Vue

2019-03-04 15:09:49

程序員互聯(lián)網(wǎng)思維模式

2020-06-15 09:32:59

程序員大公司小公司

2014-07-16 09:34:44

2022-08-01 09:43:19

程序員Googlefacebook
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)