你是否厌倦了Rickrolling?如果是这样,面部识别可能是你正在寻找的解决方案!
外国的梗“Rickrolling”到底是什么?
大致意思就是你的好友给你发一个很吸引人的东西,然后你兴致勃勃地点进去发现被超链接跳转到了Rick Astley的歌曲《Never Gonna Give You Up》的MV界面,随着这首歌开头魔性的鼓点响起,恭喜你,你就被Rickroll了。
策略
虽然通过音频指纹检测Rickroll是更直观的方法,但我相信使用面部识别是一种更有趣和可靠的方法。我相信它更可靠,因为
1.有一些Rickroll视频没有声音
2.音频可能会失真(加速、音高变化或只是低质量)
3.没有 Rick 的脸就没有 Rickroll(《Never Gonna Give You Up》由Richard演唱,Rick是Richard的昵称)
这是此操作的过于简化的流程图。
我们将使用face-recognition包,该包使用dlib的深度学习技术来识别人脸。这是通过在对象的脸上生成界标并将其保存,以与其他面部界标进行比较来实现的。
编程
导入包
首先,我们需要导入我们的包。我们将使用的三个主要包是face-recognition、opencv-python和yt-dlp。我选择了yt-dlp而不是YoutubeDL,因为我发现它下载视频的速度要快得多。
# import packages
import face_recognition # to detect Rick's face
import cv2 # to read the video
import sys
from yt_dlp import YoutubeDL # to downoad the video
import tempfile # to create a temp folder to store the downloaded video
import uuid # to create the unique folder name for the temp folder
from termcolor import colored # to add some spice to the program
下载视频
现在我们需要下载用户想要查看的 Youtube 视频。在这种情况下,URL 将作为终端中的第一个参数提供。
因此,让我们获取 URL 并设置一些其他变量,例如临时文件夹位置和我们将保存视频的路径。
# get options & set variables
youtube_url = sys.argv[1] # the video URL the user wants to check
temp_folder = f"{tempfile.gettempdir()}/{uuid.uuid1()}"# the location of the temp folder
video_location = f"{temp_folder}/output.mp4" # the location the video will be saved to
然后我们可以创建一个简单的记录器来消除输出混乱和语音错误。
# create logger for video downloader
class Logger(object):
def debug(self, msg):
pass
def warning(self, msg):
pass
def error(self, msg):
print(msg)
最后,我们可以使用yt-dlp模块下载视频。我们要确保我们制定了输出格式mp4,因为这是我们在设置video_location变量时定义的。
# download video
with YoutubeDL({
"outtmpl": f"{temp_folder}/output", # save to temp folder
"format": "bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4", # make sure it comes out as an mp4
"logger": Logger() # pipe output to logger
}) as ydl:
ydl.download([youtube_url])
print(colored("Video downloaded.", "green"))
面部识别
我们必须从 Rick Astley 的现有图片中获取面部编码。这让我们可以将它与视频中的其他面孔进行比较。
# get rick's face encoding
rick_face_encodings = [
face_recognition.face_encodings(face_recognition.load_image_file("./images/rick.jpg"))[0],
]
我们现在必须循环遍历视频中的每 10 帧以扫描面部。测试后,我决定每 10 帧检查一次,因为检查每一帧是不必要的,而且会浪费时间和系统资源。如果帧中有一张脸,我们可以获得它的编码并将其与 Rick 的脸进行比较。
让我们从捕获循环开始。
cap = cv2.VideoCapture(video_location) # create video capture
count = 0 # frame count
while True:
if count % 10 != 0: # only check every 10th frame
continue
success, frame = cap.read() # read the current frame
count += 1 # update frame count
cap.release() # release the video capture
我们现在可以在循环内搜索帧以查找任何面孔,获取它们的编码并将它们与 Rick 的进行比较。我们不会遍历帧中的所有面孔,因为我们要查找的场景只有一个人。
faces = face_recognition.face_encodings(frame) # get all the faces in the frame
if faces: # if a face is found
result = face_recognition.compare_faces(rick_face_encodings, faces[0]) # compare rick's face encoding with the one found in the frame
if result: # if the face encoding match
print(colored("Rick roll detected!", "red"))
break
else: # skip frame if there are no faces
continue
最后但并非最不重要的一点是,如果视频捕获以没有匹配结束(将其放在循环的顶部),则没有检测到 rickrolls。
if not success:
cap.release()
print(colored("No rick rolls found!", "green"))
break
现在,如果你运行python3 main.py "https://www.youtube.com/watch?v=dQw4w9WgXcQ"它应该输出Rick roll detected! .
结论
做得好!你刚刚使用面部识别制作了一个 rickroll 检测器。