<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
<script src="js/jquery-3.2.1.min.js" type="text/javascript" charset="utf-8"></script>
<script src="js/bootstrap.js" type="text/javascript" charset="utf-8"></script>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
window.onload=function(){
var vm=new Vue({
el:'.container',
data:{
arr:[],
username:'',
age:'',
nowIndex:100,
},
methods:{
add:function(){
this.arr.push({
name:this.username,
age:this.age
});
this.username='',
this.ge=''
},
delmsg:function(n){
this.arr.splice(n,1)
}
}
});
}
</script>
</head>
<body>
<div class="container">
<form role="form">
<div class="form-group">
<label for="username">用戶名:</label>
<input type="text" class="form-control"id="username"
v-model="username" placeholder="請輸入用戶名"/>
</div>
<div class="form-group">
<label for="age">年齡:</label>
<input type="text" class="form-control"id="age"
v-model="age" placeholder="請輸入用戶名"/>
</div>
<div class="form-group">
<button type="button" class="btn btn-primary btn-sm" v-on:click="add()">添加</button>
<button type="reset" class="btn btn-danger btn-sm">重置</button>
</div>
</form>
<hr/>
<table role="table" class="table table-bordered table-hover">
<tr class="text-center">
<th>序號</th>
<th>用戶名</th>
<th>年齡</th>
<th>操作</th>
</tr>
<tr v-for="(item,index) in arr">
<td>{{index+1}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td><button class="btn btn-danger btn-sm" data-toggle="modal"
data-target="#layer" v-on:click="nowIndex=index">刪除</button></td>
</tr>
<tr v-show="arr.length==0">
<td colspan="4" class="text-center">暫無數據</td>
</tr>
</table>
<!-- 模態框 -->
<div role="dialog" class="modal fade" id="layer">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span>×</span>
</button>
<div class="modal-title">確定要刪除么?</div>
</div>
<div class="modal-body text-right">
<button type="button" class="btn btn-primary btn-sm"
data-dismiss="modal">取消</button>
<button type="button" class="btn btn-danger btn-sm"
data-dismiss="modal" v-on:click="delmsg(nowIndex)">確認</button>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
里選中一行,進行刪除,只是把當前的索引傳遞過來,傳遞到模態窗,模態窗的確認按鈕,實現刪除,把傳遞過來的索引傳遞到事件中,this.arr.splice(n,1)進行刪除,切記,需要引入Jquery的js和bootstrap.js,這樣模態窗的功能輕松實現
無法訪問可以加企鵝群看離線版:1006429377
或者訪問:https://www.yuque.com/caiyongjie/snknlo/ga5ef9
官網截圖
Print.js was primarily written to help us print PDF files directly within our apps, without leaving the interface, and no use of embeds. For unique situations where there is no need for users to open or download the PDF files, and instead, they just need to print them.
One scenario where this is useful, for example, is when users request to print reports that are generated on the server side. These reports are sent back as PDF files. There is no need to open these files before printing them. Print.js offers a quick way to print these files within our apps.
Print.js主要是為了幫助我們直接在我們的應用程序中打印PDF文件,而無需離開界面,也不使用嵌入。 對于不需要用戶打開或下載PDF文件的獨特情況,相反,他們只需要打印它們。
例如,當用戶請求打印在服務器端生成的報告時,這種情況很有用。 這些報告以PDF文件形式發回。 打印前無需打開這些文件。 Print.js提供了一種在我們的應用程序中打印這些文件的快捷方式。
PDF files must be served from the same domain as your app is hosted under. Print.js uses iframe to load files before printing them, therefore, it is limited by the Same Origin Policy. This helps preventing Cross-site scripting (XSS) attacks.
必須在托管應用程序的同一域中提供PDF文件。 Print.js在打印文件之前使用iframe加載文件,因此它受同源策略的限制。 這有助于防止跨站點腳本(XSS)攻擊。
首先在頁面上添加一個按鈕
<button type="button" onclick="printJS('docs/printjs.pdf')"> Print PDF </button>
<button type="button" onclick="printJS({printable:'docs/xx_large_printjs.pdf', type:'pdf', showModal:true})"> Print PDF with Message </button>
<form method="post" action="#" id="printJS-form"> ... </form> <button type="button" onclick="printJS('printJS-form', 'html')"> Print Form </button>
<button type="button" onclick="printJS({ printable: 'printJS-form', type: 'html', header: 'PrintJS - Form Element Selection' })"> Print Form with Header </button>
<img src="images/print-01.jpg" /> printJS('images/print-01-highres.jpg', 'image') printJS({printable: 'images/print-01-highres.jpg', type: 'image', header: 'My cool image header'})
printJS({ printable: ['images/print-01-highres.jpg', 'images/print-02-highres.jpg', 'images/print-03-highres.jpg'], type: 'image', header: 'Multiple Images', imageStyle: 'width:50%;margin-bottom:20px;' })
someJSONdata = [ { name: 'John Doe', email: 'john@doe.com', phone: '111-111-1111' }, { name: 'Barry Allen', email: 'barry@flash.com', phone: '222-222-2222' }, { name: 'Cool Dude', email: 'cool@dude.com', phone: '333-333-3333' } ] <button type="button" onclick="printJS({printable: someJSONdata, properties: ['name', 'email', 'phone'], type: 'json'})"> Print JSON Data </button>
<button type="button" onclick="printJS({ printable: someJSONdata, properties: ['name', 'email', 'phone'], type: 'json', gridHeaderStyle: 'color: red; border: 2px solid #3971A5;', gridStyle: 'border: 2px solid #3971A5;' })"> Print JSON Data </button>
<button type="button" onclick="printJS({ printable: someJSONdata, properties: [ { field: 'name', displayName: 'Full Name'}, { field: 'email', displayName: 'E-mail'}, { field: 'phone', displayName: 'Phone'} ], type: 'json' })"> Print with custom table header text </button> <button type="button" onclick="printJS({ printable: someJSONdata, type: 'json', properties: ['name', 'email', 'phone'], header: '<h3 class="custom-h3">My custom header</h3>', style: '.custom-h3 { color: red; }' })"> Print header raw html </button>
npm install print-js --save //或 yarn add print-js
import print from 'print-js'
//cdn,不知道能不能訪問,我這可以訪問 https://printjs-4de6.kxcdn.com/print.min.js https://printjs-4de6.kxcdn.com/print.min.cssye <script src="print.js"></script>
<link rel="stylesheet" type="text/css" href="print.css">
詳細配置:
自IT Next,作者:Vincent Mühler,機器之心編譯,參與:Geek AI、張倩。
本文將為大家介紹一個建立在「tensorflow.js」內核上的 javascript API——「face-api.js」,它實現了三種卷積神經網絡架構,用于完成人臉檢測、識別和特征點檢測任務,可以在瀏覽器中進行人臉識別。
號外!號外!現在人們終于可以在瀏覽器中進行人臉識別了!本文將為大家介紹「face-api.js」,這是一個建立在「tensorflow.js」內核上的 javascript 模塊,它實現了三種卷積神經網絡(CNN)架構,用于完成人臉檢測、識別和特征點檢測任務。
像往常一樣,我們將查看一個簡單的代碼示例,這將使你能立即通過短短幾行代碼中的程序包開始了解這個 API。讓我們開始吧!
我們已經有了「face-recognition.js」,現在又來了另一個同樣的程序包?
如果你閱讀過本文作者另一篇關于「node.js」環境下進行人臉識別的文章《Node.js + face-recognition.js : Simple and Robust Face Recognition using Deep Learning》(Node.js + face-recognition.js:通過深度學習實現簡單而魯棒的人臉識別)(https://medium.com/@muehler.v/node-js-face-recognition-js-simple-and-robust-face-recognition-using-deep-learning-ea5ba8e852),你就會知道他在之前組裝過一個類似的程序包,例如「face-recgnition.js」,從而為「node.js」引入了人臉識別功能。
起初,作者并沒有預見到 JavaScript 社區對與人臉識別程序包的需求程度如此之高。對許多人而言,「face-recognition.js」似乎是一個不錯的、能夠免費試用的開源選項,它可以替代由微軟或亞馬遜等公司提供的付費人臉識別服務。但是作者曾多次被問道:是否有可能在瀏覽器中運行完整的人臉識別的工作流水線?
多虧了「tensorflow.js」,這種設想最終變為了現實!作者設法使用「tf.js
」內核實現了部分類似的工具,它們能得到和「face-recognition.js」幾乎相同的結果,但是作者是在瀏覽器中完成的這項工作!而且最棒的是,這套工具不需要建立任何的外部依賴,使用它非常方便。并且這套工具還能通過 GPU 進行加速,相關操作可以使用 WebGL 運行。
這足以讓我相信,JavaScript 社區需要這樣的一個為瀏覽器環境而編寫的程序包!可以設想一下你能通過它構建何種應用程序。
如何利用深度學習解決人臉識別問題
如果想要盡快開始實戰部分,那么你可以跳過這一章,直接跳到代碼分析部分去。但是為了更好地理解「face-api.js」中為了實現人臉識別所使用的方法,我強烈建議你順著這個章節閱讀下去,因為我常常被人們問到這個問題。
為簡單起見,我們實際想要實現的目標是在給定一張人臉的圖像時,識別出圖像中的人。為了實現這個目標,我們需要為每一個我們想要識別的人提供一張(或更多)他們的人臉圖像,并且給這些圖像打上人臉主人姓名的標簽作為參考數據?,F在,我們將輸入圖像和參考數據進行對比,找到與輸入圖像最相似的參考圖像。如果有兩張圖像都與輸入足夠相似,那么我們輸出人名,否則輸出「unknown」(未知)。
聽起來確實是個好主意!然而,這個方案仍然存在兩個問題。首先,如果我們有一張顯示了多人的圖像,并且我們需要識別出其中所有的人,將會怎樣呢?其次,我們需要建立一種相似度度量手段,用來比較兩張人臉圖像。
人臉檢測
我們可以從人臉檢測技術中找到第一個問題的答案。簡單地說,我們將首先定位輸入圖像中的所有人臉。「face-api.js」針對人臉檢測工作實現了一個 SSD(Single Shot Multibox Detector)算法,它本質上是一個基于 MobileNetV1 的卷積神經網絡(CNN),在網絡的頂層加入了一些人臉邊框預測層。
該網絡將返回每張人臉的邊界框,并返回每個邊框相應的分數,即每個邊界框表示一張人臉的概率。這些分數被用于過濾邊界框,因為可能存在一張圖片并不包含任何一張人臉的情況。請注意,為了對邊界框進行檢索,即使圖像中僅僅只有一個人,也應該執行人臉檢測過程。
人臉特征點檢測及人臉對齊
在上文中,我們已經解決了第一個問題!然而,我想要指出的是,我們需要對齊邊界框,從而抽取出每個邊界框中的人臉居中的圖像,接著將其作為輸入傳給人臉識別網絡,因為這樣可以使人臉識別更加準確!
為了實現這個目標,「face-api.js」實現了一個簡單的卷積神經網絡(CNN),它將返回給定圖像的 68 個人臉特征點:
從特征點位置上看,邊界框可以將人臉居中。你可以從下圖中看到人臉檢測結果(左圖)與對齊后的人臉圖像(右圖)的對比:
人臉識別
現在,我們可以將提取出的對齊后的人臉圖像輸入到人臉識別網絡中,該網絡基于一個類似于 ResNet-34 的架構,基本上與 dlib(https://github.com/davisking/dlib/blob/master/examples/dnn_face_recognition_ex.cpp)中實現的架構一致。該網絡已經被訓練去學習出人臉特征到人臉描述符的映射(一個包含 128 個值的特征向量),這個過程通常也被稱為人臉嵌入。
現在讓我們回到最初對比兩張人臉圖像的問題:我們將使用每張抽取出的人臉圖像的人臉描述符,并且將它們與參考數據的人臉描述符進行對比。更確切地說,我們可以計算兩個人臉描述符之間的歐氏距離,并根據閾值判斷兩張人臉圖像是否相似(對于 150*150 的圖像來說,0.6 是一個很好的閾值)。使用歐氏距離的效果驚人的好,當然,你也可以選用任何一種分類器。下面的 gif 動圖可視化了通過歐氏距離比較兩張人臉圖像的過程:
至此,我們已經對人臉識別的理論有所了解。接下來讓我們開始編寫一個代碼示例。
是時候開始編程了!
在這個簡短的示例中,我們將看到如何一步步地運行人臉識別程序,識別出如下所示的輸入圖像中的多個人物:
導入腳本
首先,從 dist/face-api.js 獲得最新的版本(https://github.com/justadudewhohacks/face-api.js/tree/master/dist),或者從 dist/face-api.min.js 獲得縮減版,并且導入腳本:
<script src="face-api.js"></script>
如果你使用 npm 包管理工具,可以輸入如下指令:
npm i face-api.js
加載模型數據
你可以根據應用程序的要求加載你需要的特定模型。但是如果要運行一個完整的端到端的示例,我們還需要加載人臉檢測、人臉特征點檢測和人臉識別模型。相關的模型文件可以在代碼倉庫中找到,鏈接如下:https://github.com/justadudewhohacks/face-api.js/tree/master/weights。
其中,模型的權重已經被量化,文件大小相對于初始模型減小了 75%,使你的客戶端僅僅需要加載所需的最少的數據。此外,模型的權重被分到了最大為 4 MB 的數據塊中,使瀏覽器能夠緩存這些文件,這樣它們就只需要被加載一次。
模型文件可以直接作為你的 web 應用中的靜態資源被使用,或者你可以將它們存放在另外的主機上,通過指定的路徑或文件的 url 鏈接來加載。假如你將它們與你在 public/models 文件夾下的資產共同存放在一個 models 目錄中:
const MODEL_URL = '/models'
await faceapi.loadModels(MODEL_URL)
或者,如果你僅僅想要加載特定的模型:
const MODEL_URL = '/models'
await faceapi.loadFaceDetectionModel(MODEL_URL)
await faceapi.loadFaceLandmarkModel(MODEL_URL)
await faceapi.loadFaceRecognitionModel(MODEL_URL)
從輸入圖像中得到對所有人臉的完整描述
該神經網絡可以接收 HTML 圖像、畫布、視頻元素或張量(tensor)作為輸入。為了檢測出輸入圖像中分數(score)大于最小閾值(minScore)的人臉邊界框,我們可以使用下面的簡單操作:
const minConfidence = 0.8
const fullFaceDescriptions = await faceapi.allFaces(input, minConfidence)
一個完整的人臉描述符包含了檢測結果(邊界框+分數),人臉特征點以及計算出的描述符。正如你所看到的,「faceapi.allFaces」在底層完成了本文前面的章節所討論的所有工作。然而,你也可以手動地獲取人臉定位和特征點。如果這是你的目的,你可以參考 github repo 中的幾個示例。
請注意,邊界框和特征點的位置與原始圖像/媒體文件的尺寸有關。當顯示出的圖像尺寸與原始圖像的尺寸不相符時,你可以簡單地通過下面的方法重新調整它們的大?。?/p>
const resized = fullFaceDescriptions.map(fd => fd.forSize(width, height))
我們可以通過將邊界框在畫布上繪制出來對檢測結果進行可視化:
fullFaceDescription.forEach((fd, i) => {
faceapi.drawDetection(canvas, fd.detection, { withScore: true })
})
可以通過下面的方法將人臉特征點顯示出來:
fullFaceDescription.forEach((fd, i) => {
faceapi.drawLandmarks(canvas, fd.landmarks, { drawLines: true })
})
通常,我會在 img 元素的頂層覆蓋一個具有相同寬度和高度的絕對定位的畫布(想獲取更多信息,請參閱 github 上的示例)。
人臉識別
當我們知道了如何得到給定的圖像中所有人臉的位置和描述符后,我們將得到一些每張圖片顯示一個人的圖像,并且計算出它們的人臉描述符。這些描述符將作為我們的參考數據。
假設我們有一些可以用的示例圖片,我們首先從一個 url 鏈接處獲取圖片,然后使用「faceapi.bufferToImage」從它們的數據緩存中創建 HTML 圖像元素:
// fetch images from url as blobs
const blobs = await Promise.all(
['sheldon.png' 'raj.png', 'leonard.png', 'howard.png'].map(
uri => (await fetch(uri)).blob()
)
)
// convert blobs (buffers) to HTMLImage elements
const images = await Promise.all(blobs.map(
blob => await faceapi.bufferToImage(blob)
))
接下來,在每張圖像中,正如我們之前對輸入圖像所做的那樣,我們對人臉進行定位、計算人臉描述符:
const refDescriptions = await Promsie.all(images.map(
img => (await faceapi.allFaces(img))[0]
))
const refDescriptors = refDescriptions.map(fd => fd.descriptor)
現在,我們還需要做的就是遍歷我們輸入圖像的人臉描述符,并且找到參考數據中與輸入圖像距離最小的描述符:
const sortAsc = (a, b) => a - b
const labels = ['sheldon', 'raj', 'leonard', 'howard']
const results = fullFaceDescription.map((fd, i) => {
const bestMatch = refDescriptors.map(
refDesc => ({
label: labels[i],
distance: faceapi.euclideanDistance(fd.descriptor, refDesc)
})
).sort(sortAsc)[0]
return {
detection: fd.detection,
label: bestMatch.label,
distance: bestMatch.distance
}
})
正如前面提到的,我們在這里使用歐氏距離作為一種相似度度量,這樣做的效果非常好。我們在輸入圖像中檢測出的每一張人臉都是匹配程度最高的。
最后,我們可以將邊界框和它們的標簽一起繪制在畫布上,顯示檢測結果:
// 0.6 is a good distance threshold value to judge
// whether the descriptors match or not
const maxDistance = 0.6
results.forEach(result => {
faceapi.drawDetection(canvas, result.detection, { withScore: false })
const text = `${result.distance < maxDistance ? result.className : 'unkown'} (${result.distance})`
const { x, y, height: boxHeight } = detection.getBox()
faceapi.drawText(
canvas.getContext('2d'),
x,
y + boxHeight,
text
)
})
至此,我希望你對如何使用這個 API 有了一個初步的認識。同時,我也建議你看看文中給出的代碼倉庫中的其它示例。好好地把這個程序包玩個痛快吧!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。