使用 Python 进行简单的人脸识别

通过使用 Python 进行简单的人脸识别非常简单,使用到了 OpenCV 库内的 haarcascade_frontalface_default.xml ,haarcascade 包含经过训练的用于检测对象的特定类型的分类器,例如:人脸,人眼,倾斜的人脸,鼻子,口嘴,微笑,上半身,下半身等。

代码

import cv2
import os


def load_img(path, name, mun=30, add_with=0):
    if not os.path.exists(path):
        os.mkdir(path)
    # 获取人脸识别模型
    classfier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml文件路径')
    # 创建一个窗口
    cv2.namedWindow('Face')
    # 使用内置摄像头
    cap = cv2.VideoCapture(0)
    # 使用视频进行识别
    # cap = cv2.VideoCapture('视频路径')
    # 根据摄像头设置IP及rtsp端口
    # url='rtsp://admin:admin@192.168.0.104:8554/live'
    # cap = cv2.VideoCapture(url)
    i = 0  # 计数
    if cap.isOpened():
        while i < mun:
            ok, frame = cap.read()  # 读取一帧图片
            if not ok:
                continue

            faces = classfier.detectMultiScale(frame, 1.3, 5, minSize=(32, 32))

            if len(faces) > 0:
                for face in faces:
                    x, y, w, h = face

                    img = frame[y - add_with:y + h + add_with, x - add_with:x + w + add_with]
                    # 显示人脸框
                    cv2.rectangle(frame, (x - add_with, y - add_with), (x + w + add_with, y + h + add_with),
                                  (0, 255, 0), 2)
                    save_path = path + '/' + name + '_' + str(i) + '.jpg'
                    print(save_path)
                    img2 = cv2.resize(img, (112, 112))
                    cv2.imwrite(save_path, img2)
                    i += 1

            cv2.imshow('face', frame)
            c = cv2.waitKey(10)
            if c & 0xFF == ord('q'):
                break

        cap.release()
        cv2.destroyAllWindows()


if __name__ == '__main__':
    # 第一个参数为保存图片的路径
    # 第二个参数为保存图片名字的开头
    # 第三个参数为图片的数量
    # 第四个参数可以调节图片的大小
    load_img('保存图片文件夹路径', 'lq', 500, 0)

Git 删除历史记录,清理仓库

当 commit 次数很多的时候,项目仓库会慢慢积攒很多无用的提交历史,这些历史记录会在项目 clone 的时候导致速度很慢。如果没有软件,一些 clone 过程体验会很不好,甚至频繁出错,所以删除提交历史可以作为一种清理仓库的手段。

Git 代码

git checkout --orphan latest_branch
git add -A
git commit -am "init commit"
git branch -D master
git branch -m master
git push -f origin master

以下是各条语句的解析

git checkout --orphan latest_branch
# 创建新分支 "latest_branch" 并转到该分支
# git checkout 命令为在当前分支上创建新分支(并转到该分支)
# git checkout --orphan 命令为从空白处创建新分支(并转到该分支)

git add -A
# 添加所有文件(当前最新状态)到暂存区

git commit -am "commit message"
# 将暂存区提交到新纪录(latest_branch分支)
# "commit message"为新纪录的名称

git branch -D master
# 删除主分支

git branch -m master
# 将 latest_branch(当前) 分支重命名为 master(主分支)

git push -f origin master
# 同步本地状态到服务器

# 此时,完成的效果为:
#   将master分支所有记录删除,并新建一个 "commit message" 记录,记录中内容为当前项目最新状态
#   此时远程服务器内所有垃圾都被清空
#   如果使用了 Github Desktop 等软件,本地垃圾可能未被清空,可删除项目并重新 clone

Element Plus Table(表格)点击获取对应 id

网上搜到的内容或许适用于 vue 2 或 Element UI,不适用 vue 3 和 Element Plus。

template:

<el-table-column label="配置" width="120" align="center">
  <template v-slot="scope">
    <el-button link type="primary" size="small">编辑</el-button>
    <el-button link type="primary" @click="deleteNavigation(scope.row.id)" size="small">删除
    </el-button>
  </template>
</el-table-column>

script:

function deleteNavigation(id) {
  console.log(id);
}

使用 vue 的 v-slot 指令,这个指令中是 vue 2.6 新增的,取代了以前的 slot 和 slot-scope,而我使用的是 vue 3,所以网上搜到的很多使用 slot-scope 的方法都失效了。

使用 插槽名.row 可以获取一行的内容,如果要获取行内的某一个字段的值,只需要再点出它的字段名,在我的代码里,就是 scope.row.id

如果要获取行的索引,使用 插槽名.$index,注意$符号是必不可少的,否则将不起作用。

[] == false 和 !![] == true 解析

==是相等操作符,先转换再比较;===是全等操作符,仅比较不转换。

[] == false 解析

右侧布尔值很简单,直接转换成 0

[] 不是基本数据类型,它是对象,所以需要调用 valueOf 方法(Array.prototype.valueOf() ,但是 Array 没有实现 valueOf 方法,所以根据原型链,最终调用的是 Object.prototype.valueOf):

[].valueOf():得到的仍然是 [] ,继续调用 toString 方法(Array.prototype.toString()):

[].toString():得到""

""作为基本数据类型直接调用 Number("") 得到 0

所以最终结果是 true


!![] == true

!!== 的优先级更高,所以先看 !![]

![] 得到 false (操作数是对象的话逻辑非返回 false),然后再取非,得到 true

很明显,true == true 得到的结果是 true

Vue 3 兄弟组件间传值

Vue 3 中兄弟间传值可以使用 Vuex,但小项目使用过于庞大,我们可以使用 mitt 进行兄弟组件间传值。

操作步骤

第一步:安装 mitt

npm i mitt

第二步:创建文件(例如:eventBus.js

import mitt from 'mitt'

const emitter = mitt()
export default emitter

第三步:将该文件引入至需要进行发送及接受的 .vue 文件中

import emitter from "../untils/bus";

第四步:发送端写入下列代码

emitter.emit("response", response)

前面是事件,后面是要传入的参数

第五步:接收端写入下列代码

emitter.on("response", (response) => {
    console.log(response)
})

这样两个组件间就可以进行传值通信了。

Vue 3 锚点实现方式

当我们使用 Vue 3 有时候需要做业内锚点跳转,使用传统的 a href 已经不是很推荐了,我们可以尝试采用以下方法来进行替代

标题锚点

<div class="cardTagContainer">
    <div class="cardTag" v-for="(cardGroup,index) in card.cardInfo" :key="cardGroup" @click="goAnchor('#tag' + index)">
        {{ cardGroup.title }}
    </div>
</div>

跳转内容

<h1 :id="'tag' + index">
    {{ cardGroup.title }}
</h1>

相关方法

// 标题锚点
function goAnchor(selector) {
    // console.log(selector)
    document.querySelector(selector).scrollIntoView({
        behavior: "smooth",
        block: "start"
    });
}

.scrollIntoView 属性方法

scrollIntoView() 方法将调用它的元素滚动到浏览器窗口的可见区域。

PS:根据其他元素的布局,元素可能无法完全滚动到顶部或底部。

TIPS:页面(容器)可滚动时才有用!

element.scrollIntoView(); // 等同于element.scrollIntoView(true)
element.scrollIntoView(alignToTop); // 布尔参数
element.scrollIntoView(scrollIntoViewOptions); // 对象参数