js人脸识别

<!DOCTYPE html>  
<head> 
 <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />  
    <script type="text/javascript" src="http://www.jq22.com/demo/tracking-Plus201710110918/js/tracking-min.js"></script>
    <script type="text/javascript" src="http://www.jq22.com/demo/tracking-Plus201710110918/js/face-min.js"></script>
    <style type="text/css">
        .v{
            margin-left: -9999px;
            float: left;
        }
    </style>
</head>  
<body>  
    <input type="button" title="开启摄像头" value="开启摄像头" onclick="getMedia();" /><br />   
    <video height="320px" class="v" id="video" autoplay="autoplay"></video><hr />   
    <canvas id="canvas" width="480px" height="320px"></canvas>  
    <script type="text/javascript">  
    let video = document.getElementById('video');
    let canvas = document.getElementById('canvas');
    let context = canvas.getContext('2d');
    context.lineWidth = 10;
    context.strokeStyle = '#ff0202';
    function getUserMedia(constraints, success, error) {
        if (navigator.mediaDevices.getUserMedia) {
            //最新的标准API
            navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
        } else if (navigator.webkitGetUserMedia) {
            //webkit核心浏览器
            navigator.webkitGetUserMedia(constraints,success, error)
        } else if (navigator.mozGetUserMedia) {
            //firfox浏览器
            navigator.mozGetUserMedia(constraints, success, error);
        } else if (navigator.getUserMedia) {
            //旧版API
            navigator.getUserMedia(constraints, success, error);
        }
    }
    function success(stream) { 
        let CompatibleURL = window.URL || window.webkitURL; 
        video.srcObject = stream;
        video.play();
    }
    function error(error) {
        alert('访问用户媒体设备失败,请尝试更换浏览器')
    }
    function getMedia() {
        if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
            getUserMedia({video : {width: 480, height: 320 }}, success, error);
        } else {
            alert('不支持访问用户媒体');
        }
    }
    var tracker = new tracking.ObjectTracker(['face']);
    tracker.setStepSize(1.7);
    tracking.track('#video', tracker);
    tracker.on('track', function(event) {
       // context.clearRect(0, 0, canvas.width, canvas.height); 
        context.drawImage(video,0,0,480,320);
        if(event.data.length == 0){
            console.log("没有检测到人脸")
        }else{
            event.data.forEach(function(rect) {
            context.strokeRect(rect.x, rect.y, rect.width, rect.height);
        });            
        }
      });
    </script>  
</body>


电路知识

串联电路中的电流处处相等。 

并联电路干路中的电流等于各支路中的电流之和。


串联电路中电源两端电压等于各用电器两端电压之和,用符号表示时可以写为

U=U1 +U2

并联电路中电源两端电压与各支路用电器两端的电压相等,用符号表示时可以写为

U=U1 =U2


I = UR


其中 U 的单位为伏特(V),R 的单位为欧姆 (Ω),I 的单位为安培(A)。


1 kW · h(千瓦时) = 1×103 W×3 600 s = 3.6×106 J


电功率是描述电流做功快慢的物理量,它的定义式是P= Wt 即电功与时间之比

电功率与电流和电压的关系是 P = UI。利用这个关系式,可以测出用电器的实际用电 功率。


电路两端的电压为 U ,电路中的电流为 I ,通电时间为t时,电 功 W(或者说消耗的电能)为

W=UIt

例题 有一只节能灯接在 220 V 的家庭电路中,通过它的电流为 0.09 A

计算这只灯使用 5 h 用电多少千瓦时。W = UIt = 220 V × 0.09 A × 5 h= 0.099 kW·h

所以,这只节能灯工作 5 h 消耗的电能是 0.099 kW · h


在物理学中,用电功率(electric power)表示 电流做功的快慢。电功率用 P 表示,它的单位是瓦 特(watt),简称,符号是 W。前面提到的 24 W500 W,说的就是用电器的电功率。


作为表示电流做功快慢的物理量,电功率等于 电功与时间之比。如果电功用 W 表示,完成这些电 功所用的时间用 t 表示 ,电功率用 P 表示,则

P = Wt

将上节电功 W = UIt 代入上式得P = UI





知微:Switch与If误区

最新想写一些关于编程细致末梢的文章,叫做知微。看文章需要有一定的逆向基础与汇编知识。如果不会的话,不建议阅读。以免给你灌输了错误的思想,而你无法发现。知微相关的文章不保证正确性,只是对发现或者知识点的一种证明。

大概很久以前,对于switch和if。某视频里面说了一句,switch比if要快。于是这个概念就一直记忆到现在。每次碰到这个问题,我基本上都会告诉别人switch比if快。但是为什么快?怎么快的?估计很大一部分人就不知道了。或者说没有听过它俩谁快的说法,代码的编写更因该关注一些细节。毕竟大的方向,框架,算法逻辑什么的,你不一定会写。小的地方你又不了解。那你只是个Copy+C,Copy+V的选手,也无法进步。

同样的代码有两个版本:release 和 debug。这里拿debug来说,为什么拿debug来说,这有涉及到这两个版本的优化问题。可自行查阅相关编译器、解释器的说明。注意它俩并非是名称上的不同。

来看一下两个判断代码:

switch.png


if.png

然后来看一下汇编代码

debug-switch.png

debug-if.png

汇编代码关键的地方我已经备注了,可以发现if语句是每条都会进行判断,有一定的浪费,而switch通过数组直接会索引到相关的printf语句,是比较快的。

知微:上拉引申的IF

昨天晚上想到一个问题,对于页面的上拉操作,当多次触发上拉动作时如何避免多次请求。于是这样实现了一下。

let i=0
if(i==0)
    up

发现这样可以解决多次上拉问题。看似解决了,不过其中的if判断语句存在一个条件竞争的问题。于是想了一条理由,是由于JavaScript编译执行的逻辑问题,造成的一定延迟,所以没有存在条件竞争。于是我用C++重新写了一个类似的。

#include "windows.h"
int i = 0; 
DWORD WINAPI ThreadProc2(LPVOID lpParam)
{
    Sleep(300);
    printf( "3,");
    i = 0;
    return 0;
}
DWORD WINAPI ThreadProc1(LPVOID lpParam)
{
    if (i == 0){
        i = 1;
        printf( "0,");
        CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
    }
    else
    {
        printf( "1,");
    }
    return 0;
}
  
int _tmain(int argc, _TCHAR* argv[])
{ 
    for (size_t i = 0; i < 1000; i++)
    {
        CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
    }
    getchar();
    return 0;
}

于是你会发现它还是很好的解决了上拉的问题。由于C++编译后的opcode接近机器码,所以JavaScript存在的编译执行问题,它不存在。但是它依旧没有多次打印“0”。这里伪造多次是通过线程。让我想到Cpu的问题。Cpu切片和线程执行。从代码来看,它存在竞争问题,但是总和一些外在因素,它规避了问题。想来想去还是没有答案,为什么会规避掉竞态问题。