FFmpeg (一)使用opencv实现马赛克

课程组成:Shell、FFmpeg、OpenCV

  1. Shell脚本 作用:主要用于交叉编译,编译出移动端可用的 FFmpeg / OpenCV 二进制库(.a静态库、.so动态库)。 不需要精通Shell全部语法,重点看懂编译脚本、configure配置、多平台编译逻辑,能修改编译参数即可。
  2. FFmpeg 作用:音视频编解码核心。负责读取音视频文件、解封装、解码,输出原始音视频帧数据(视频输出YUV帧,音频输出PCM);也可以把处理完成的原始帧重新编码、封装,输出成MP4等视频文件。 关注点:解封装‑解码‑渲染‑编码‑封装完整流程、pts/dts时间戳、音视频同步。
  3. OpenCV 作用:图像算法处理,做滤镜、像素运算、轮廓检测等。 工作模式:接收FFmpeg解码出来的每一帧图像,做单帧图像处理;处理完成后,再把帧交还给FFmpeg进行编码导出。 核心数据结构:cv::Mat,C++对象,OC不能直接调用,需要OC++混编。

完整数据流链路 视频文件 → FFmpeg解封装解码 → YUV原始帧 →(格式转换YUV→BGR)→ OpenCV做滤镜/图像处理 → 转回YUV → FFmpeg编码封装 → 输出新视频文件

openCV 实现图片的马赛克

C++前置知识。

arduino 复制代码
// opencv的UIImage对象,对比UIImage,cv::Mat可以拿到每一个像素点
cv::Mat cvImage;

#import <opencv2/opencv.hpp>
    cv::Mat cvImage; // 可以直接用命名空间+类名
//    Mat cvImage3; 编译报错
    using namespace cv; // 使用命名空间后,可以直接使用类名。
    Mat cvImage2;

从opencv.org下载一个opencv2.framework。

ImageUtils.h

objectivec 复制代码
#import <UIKit/UIKit.h>

@interface ImageUtils : NSObject

//定义方法:处理图片
+ (UIImage *)mosaicImage:(UIImage *)image level:(int)level;
    
@end

ImageUtils.mm 有C++文件,不能直接用.m后缀

这里为了强调哪些是opencv的类,没有使用命名空间。

arduino 复制代码
#import "ImageUtils.h"
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>

@implementation ImageUtils

+ (UIImage *)mosaicImage:(UIImage *)image level:(int)level{
    cv::Mat cvImage;
    // 将OC对象的UIImage转opencv格式的Mat对象
    UIImageToMat(image, cvImage);
    
    // 这个cv::Mat可以拿到宽度和高度
    int width = cvImage.cols;       // cols 列 = 宽度
    int height = cvImage.rows;      // rows 行 = 高度
    NSLog(@"图片的宽是%d 高是%d",width,height);
    
    
    // iOS 的 UIImage 转 Mat 之后,得到的是 RGBA4 通道,带透明度 Alpha
    // CV_RGBA2RGB:将带透明通道的RGBA转成RGB的Mat对象
    // 最后一个参数dstCn如果设置0,就会根据前面code自动推断输出通道;也可以写3
    // 如果写4,会强制输出4通道,Alpha通道值填充为0
    //
    cv::Mat cvImage2;
    cv::cvtColor(cvImage, cvImage2, CV_RGBA2RGB, 0);
    
    
    // 开始进行马赛克
    // x:列,横向遍历
    for (int x=0; x < width-level; x+=level) {
        // y:行,纵向遍历
        for (int y=0; y<height-level; y+= level) {
            
            // 创建一个矩形区域
            // Rect2i
            // React表示矩形
            // 2 表示二维
            // i 代表int整数类型,像素坐标
            // 参数分别表示(左上角的X坐标,左上角的y坐标,右下角的x坐标,右下角的y坐标)
            cv::Rect2i mosaicRect = cv::Rect2i(x, y, level, level);
            
            // 从RGB的图像中取出这部分矩形的ROI区域
            // 这里是浅拷贝,只生成新Mat头,像素数据和cvImage2共用同一块内存
            // 修改roi的像素,会直接修改cvImage2原图的像素
            cv::Mat roi = cvImage2(mosaicRect);
            
            
            
            
            // 读取方块左上角(y行,x列)像素点的RGB值
            // cv::Scalar是opencv的颜色容器,用来保存颜色分量
            // ⚠️ .at<Vec3b>(行号y, 列号x),行在前,列在后!!
            cv::Scalar scalar = cv::Scalar(cvImage2.at<cv::Vec3b>(y,x)[0],
                                           cvImage2.at<cv::Vec3b>(y,x)[1],
                                           cvImage2.at<cv::Vec3b>(y,x)[2]);
            
            // 新建一张和马赛克方块一样大小的纯色图像,整块全部填充 scalar 指定的颜色。
            // 8U:8位无符号,取值0~255
            // C3:3个通道,RGB三通道
            cv::Mat roiCopy = cv::Mat(mosaicRect.size(), CV_8UC3, scalar);
            
            // 将这个小矩形的图片全部填充为这个纯色的图片
            roiCopy.copyTo(roi);
        }
    }
    return MatToUIImage(cvImage2);
}
相关推荐
开开心心就好2 天前
手机虚拟化学实验室,混合燃烧都能模拟
jupyter·智能手机·ffmpeg·计算机外设·电脑·音视频·visual studio
VidDown2 天前
用户说“卡顿“,服务器一切正常:播放质量监测与 QoE 指标
运维·服务器·ffmpeg·音视频·视频
开开心心就好2 天前
手机电池健康怎么查?看容量温度循环次数
spring·智能手机·ffmpeg·计算机外设·电脑·maven·音视频
智能直播4 天前
网络RTMP拉流不卡顿、声音不同步,一文讲透缓冲区、时间戳
开发语言·ffmpeg·php·音视频·视频编解码
八月的雨季 最後的冰吻4 天前
FFmepg-- 42-ffplay.c 线程安全机制深度分析
c语言·安全·ffmpeg
开开心心就好5 天前
把手机变成电脑麦克风,WiFi连接就能用
智能手机·ffmpeg·计算机外设·电脑·word·音视频
@嵌入式扫地僧5 天前
FFmpeg 解码 H.264 流提取 SEI 用户数据实战
ffmpeg·h.264·流媒体开发·sei 解析·自定义 sei
VimorphTech5 天前
ffmpeg.wasm 实战:浏览器提取视频音频,如何处理进度、取消和资源释放?
ffmpeg
小小龙学IT5 天前
FFmpeg 开源多媒体处理框架深度解析:从命令行到 libav* 全家桶
c语言·ffmpeg·开源
ofoxcoding6 天前
Gemini TTS 与 ElevenLabs 语音合成实测:同一段视频旁白效果对比
ai·ffmpeg·音视频