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);
}
相关推荐
cpp_learner1 小时前
FFmpeg RTSP播放时钟实现揭秘
ffmpeg
程序员老陆8 天前
WHIP 与 WHEP:WebRTC 直播的标准化入口与出口
ffmpeg·音视频·webrtc·whip·whep
可乐鸡翅yeah_9 天前
混合内容 Mixed‑Content 安全策略,HLS HTTPS 页面加载 HTTP 资源排错实战
运维·ffmpeg·音视频·媒体·m3u8
刘广睿9 天前
视频导出为什么发灰?色彩空间与色彩范围(BT.601/709/2020)的 ffmpeg 转换实战
ffmpeg·音视频·视频处理·色彩空间·素材管理
yivifu10 天前
精选FFmpeg 实用音频视频转换命令集
ffmpeg·音视频转换
风哥2号13 天前
数据库教程FGMT02‑生产环境Linux+Oracle19c安装配置与项目实战
linux·数据库·ffmpeg
Bruce_Liuxiaowei14 天前
录屏片段无损合并:从 ffmpeg concat 原理到 Python 自动化脚本
python·ffmpeg·自动化
工具派15 天前
口播视频怎么自动剪掉冷场?视频静音删除的阈值实测
ffmpeg·音视频·视频
❀͜͡傀儡师15 天前
移动端 360° 商品展示方案:从 20MB 雪碧图到 800KB 丝滑视频
ffmpeg·webgl·sprite