像素脸战士 PixelFace Warrior——实时处理视屏流风格变化

目录

拓展版效果演示

🎯 普通版效果演示:

pixel_size = 6

pixel_size = 10

pixel_size = 20 

pixel_size = 50

代码分析

一、项目背景与目标

二、关键技术与模块划分

三、代码实现思路

1. 初始化模块

2. FPS 统计初始化

3. 主循环结构

4. 图像预处理与人脸检测

5. 人脸像素化与网格叠加

6. 实时帧率统计与显示

7. 显示图像与结束控制

四、运行效果展示

你们最喜欢的部分来啦——整体代码

拓展方向

方向2拓展

完整代码


拓展版效果演示

风格变换

🎯 普通版效果演示:

  • 实时检测人脸

  • 对人脸区域进行像素化处理

  • 其他部分不变,像戴了一个像素面具

pixel_size = 6

pixel_size = 10

pixel_size = 20 

pixel_size = 50


代码分析

一、项目背景与目标

        在计算机视觉与图像处理的学习过程中,实时视频处理是非常有趣而实用的一个应用场景。本项目旨在利用 OpenCV 实现一个基于摄像头的实时人脸检测系统,并对检测到的人脸进行像素化处理,模拟出类似复古游戏中的像素人物效果。同时,系统提供实时 FPS(帧率)显示,用于监测系统性能。


二、关键技术与模块划分

本项目主要包括以下核心模块:

  1. 摄像头视频流读取

  2. 人脸检测(使用 Haar 特征分类器,在之前的文章中有详细的说过底层原理:人脸识别鼻祖!!——级联分类器(Cascade Classifier)详解_haar级联分类器(cv2.cascadeclassifier)-CSDN博客

  3. 图像像素化处理

  4. 网格线叠加(增强像素感)

  5. FPS 实时统计与显示


三、代码实现思路

1. 初始化模块

import cv2
import numpy as np
import time

引入所需模块:

  • cv2 是 OpenCV 的核心模块;

  • numpy 用于图像矩阵处理;

  • time 用于帧率统计。

face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
cap = cv2.VideoCapture(0)
pixel_size = 10

  • 加载人脸检测器(Haar Cascade);

  • 打开默认摄像头;

  • 设置像素块大小 pixel_size


2. FPS 统计初始化

prev_time = time.time()
frame_count = 0
fps = 0

使用时间差计算当前帧率:记录上一秒时间、当前帧计数。


3. 主循环结构

while True:
    ret, frame = cap.read()
    if not ret:
        break

  • 读取摄像头一帧图像;

  • 如果读取失败,则终止程序。


4. 图像预处理与人脸检测

frame = cv2.flip(frame, 1)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.1, 5)

  • 将图像进行镜像处理(更符合用户习惯);

  • 转换为灰度图像,提高检测速度;

  • 使用多尺度人脸检测方法,返回所有人脸位置。


5. 人脸像素化与网格叠加

for (x, y, w, h) in faces:
    face = frame[y:y+h, x:x+w]

    small = cv2.resize(face, (w // pixel_size, h // pixel_size), interpolation=cv2.INTER_LINEAR)
    pixel_face = cv2.resize(small, (w, h), interpolation=cv2.INTER_NEAREST)

    for i in range(0, h, pixel_size):
        cv2.line(pixel_face, (0, i), (w, i), (0, 0, 0), 1)
    for j in range(0, w, pixel_size):
        cv2.line(pixel_face, (j, 0), (j, h), (0, 0, 0), 1)

    frame[y:y+h, x:x+w] = pixel_face

  • 提取人脸区域;

  • 缩小再放大实现像素风格;

  • 使用 cv2.line() 添加黑色网格线;

  • 将像素化图像替换回原图。


6. 实时帧率统计与显示

frame_count += 1
current_time = time.time()
elapsed_time = current_time - prev_time

if elapsed_time >= 1.0:
    fps = frame_count / elapsed_time
    frame_count = 0
    prev_time = current_time

  • 每一帧累加计数;

  • 每秒更新一次 FPS 值,保证数字稳定;

cv2.putText(frame, f"FPS: {fps:.2f}", (10, 30),
            cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)

  • 将 FPS 以绿色字体叠加到图像左上角。


7. 显示图像与结束控制

cv2.imshow("像素脸 with FPS", frame)

if cv2.waitKey(1) == 27:  # ESC 键
    break

cap.release()
cv2.destroyAllWindows()

  • 显示处理后的视频流;

  • 当用户按下 ESC 键(ASCII码27)时退出;

  • 最后释放资源,关闭窗口。


四、运行效果展示

运行后,系统将:

  • 实时捕捉用户的脸部区域;

  • 将人脸转换为像素块风格,叠加网格线;

  • 实时在左上角显示当前 FPS 值;

  • 用户按下 ESC 键后退出程序。


你们最喜欢的部分来啦——整体代码

import cv2
import numpy as np
import time  # 用于计算时间,进而计算 FPS

# 加载人脸检测模型
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")

# 打开摄像头
cap = cv2.VideoCapture(0)
# 越小像素越小,像素块越多
pixel_size = 10

# 初始化时间和帧数,用于 FPS 计算
prev_time = time.time()
frame_count = 0
fps = 0

while True:
    ret, frame = cap.read()
    if not ret:
        break

    frame = cv2.flip(frame, 1)  # 镜像翻转
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 转为灰度图像
    faces = face_cascade.detectMultiScale(gray, 1.1, 5)

    for (x, y, w, h) in faces:
        face = frame[y:y+h, x:x+w]

        # 缩小再放大,像素化
        small = cv2.resize(face, (w // pixel_size, h // pixel_size), interpolation=cv2.INTER_LINEAR)
        pixel_face = cv2.resize(small, (w, h), interpolation=cv2.INTER_NEAREST)

        # 添加像素网格线
        for i in range(0, h, pixel_size):
            cv2.line(pixel_face, (0, i), (w, i), (0, 0, 0), 1)
        for j in range(0, w, pixel_size):
            cv2.line(pixel_face, (j, 0), (j, h), (0, 0, 0), 1)

        frame[y:y+h, x:x+w] = pixel_face

    # ======================
    # FPS 计算与显示部分👇
    # ======================
    frame_count += 1
    current_time = time.time()
    elapsed_time = current_time - prev_time

    if elapsed_time >= 1.0:  # 每秒更新一次 FPS 显示
        fps = frame_count / elapsed_time
        frame_count = 0
        prev_time = current_time

    # 在左上角绘制 FPS 文本
    cv2.putText(frame, f"FPS: {fps:.2f}", (10, 30),
                cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)

    cv2.imshow("像素脸 with FPS", frame)

    if cv2.waitKey(1) == 27:  # ESC 退出
        break

cap.release()
cv2.destroyAllWindows()

拓展方向

  1. 支持视频录制、截图;

  2. 增加像素风特效(例如低饱和度、复古色调);

  3. 用 DNN 替换 Haar,提升检测效果;

  4. 制作“像素化 GIF 表情包”功能;

  5. 添加语音播报或趣味提示文字。


方向2拓展

完整代码

import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont


# 特效模式设置(保持三通道输出)
def apply_effect(frame, mode):
    # 确保输入为三通道
    if len(frame.shape) == 2:
        frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)

    if mode == 'normal':
        return frame
    elif mode == 'desaturate':  # 灰度模式
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        return cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
    elif mode == 'sepia':  # 复古色调
        sepia_filter = np.array([
            [0.393, 0.769, 0.189],
            [0.349, 0.686, 0.168],
            [0.272, 0.534, 0.131]
        ])
        sepia_img = cv2.transform(frame, sepia_filter)
        return np.clip(sepia_img, 0, 255).astype(np.uint8)
    elif mode == 'invert':  # 反色
        return cv2.bitwise_not(frame)
    elif mode == 'redblue':  # 红蓝分离
        frame_rb = frame.copy()
        frame_rb[:, :, 1] = 0  # 去除绿色通道
        return frame_rb
    elif mode == 'cartoon':  # 卡通效果
        # 转换为灰度并模糊
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        gray = cv2.medianBlur(gray, 5)

        # 边缘检测
        edges = cv2.adaptiveThreshold(gray, 255,
                                      cv2.ADAPTIVE_THRESH_MEAN_C,
                                      cv2.THRESH_BINARY, 9, 9)

        # 颜色处理
        color = cv2.bilateralFilter(frame, 9, 300, 300)

        # 合并效果
        cartoon = cv2.bitwise_and(color, color, mask=edges)
        return cartoon


# 绘制中文文本函数
def draw_text(frame, text, position, font_size=30, color=(255, 255, 255), max_width=100):
    # 确保输入为三通道BGR格式
    if len(frame.shape) == 2:
        frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)

    # 转换为PIL格式(RGB)
    pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(pil_img)

    try:
        font = ImageFont.truetype("simhei.ttf", font_size)
    except:
        font = ImageFont.load_default()

    # 自动调整字体大小
    text_bbox = draw.textbbox((0, 0), text, font=font)
    text_width = text_bbox[2] - text_bbox[0]

    if text_width > max_width:
        font_size = int(font_size * max_width / text_width)
        font = ImageFont.truetype("simhei.ttf", font_size)

    # 计算居中位置
    text_bbox = draw.textbbox((0, 0), text, font=font)
    x = position[0] + (max_width - (text_bbox[2] - text_bbox[0])) // 2
    y = position[1] + (40 - (text_bbox[3] - text_bbox[1])) // 2

    draw.text((x, y), text, font=font, fill=color)

    # 转换回OpenCV格式
    return cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)


# 初始化摄像头
cap = cv2.VideoCapture(0)
face_cascade = cv2.CascadeClassifier(
    cv2.data.haarcascades + "haarcascade_frontalface_default.xml")

# 界面设置
mode = 'normal'
buttons = {
    "原始像素": (10, 50, 110, 90),
    "灰度像素": (10, 100, 110, 140),
    "复古像素": (10, 150, 110, 190),
    "反色像素": (10, 200, 110, 240),
    "红蓝分离": (10, 250, 110, 290),
    "漫画像素": (10, 300, 110, 340),
}
name_to_mode = {k: v for k, v in zip(
    buttons.keys(), ['normal', 'desaturate', 'sepia', 'invert', 'redblue', 'cartoon'])}


# 鼠标回调函数
def mouse_callback(event, x, y, flags, param):
    global mode
    if event == cv2.EVENT_LBUTTONDOWN:
        for name, (x1, y1, x2, y2) in buttons.items():
            if x1 <= x <= x2 and y1 <= y <= y2:
                mode = name_to_mode[name]


cv2.namedWindow("Pixel Effect")
cv2.setMouseCallback("Pixel Effect", mouse_callback)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # 确保三通道输入
    if frame.shape[2] == 1:
        frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)

    frame = cv2.flip(frame, 1)
    processed = apply_effect(frame.copy(), mode)

    # 人脸检测和像素化
    gray = cv2.cvtColor(processed, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.1, 5)

    pixel_size = 10
    for (x, y, w, h) in faces:
        # 像素化处理
        face_roi = processed[y:y + h, x:x + w]
        small = cv2.resize(face_roi, (w // pixel_size, h // pixel_size))
        pixelized = cv2.resize(small, (w, h), interpolation=cv2.INTER_NEAREST)

        # 添加网格线
        for i in range(0, h, pixel_size):
            cv2.line(pixelized, (0, i), (w, i), (0, 0, 0), 1)
        for j in range(0, w, pixel_size):
            cv2.line(pixelized, (j, 0), (j, h), (0, 0, 0), 1)

        processed[y:y + h, x:x + w] = pixelized

    # 绘制按钮
    for name, (x1, y1, x2, y2) in buttons.items():
        color = (0, 255, 0) if name_to_mode[name] == mode else (100, 100, 100)
        cv2.rectangle(processed, (x1, y1), (x2, y2), color, -1)
        processed = draw_text(processed, name, (x1, y1),
                              font_size=20, max_width=100)

    cv2.imshow("Pixel Effect", processed)
    if cv2.waitKey(1) == 27:
        break

cap.release()
cv2.destroyAllWindows()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WenJGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值