C++ 使用ffmpeg解码video模块,包括CPU解码和GPU解码,使用opencv读写视频和叠加roi,读取并反序列化检测点txt文件并使用opencv叠加轨迹。

仓库代码地址:https://gitee.com/liudegui/video_decode_detect_bbox_example

解码、检测和视频叠加

解码

使用ffmpeg解码video模块,包括CPU解码和GPU解码

检测

使用opencv官方示例中的人脸检测模型检测(haarcascade),将检测点结果序列化成字符串,写入txt文件中。

视频和roi叠加

使用opencv读写视频和叠加roi,读取并反序列化检测点txt文件并使用opencv叠加。

目录结构

  • decode_video:视频解码库;

  • mock_detect:使用opencv视频检测库;

  • detect_video:集成解码、检测程序;

  • video_bbox_drawer:视频叠加roi程序。


使用C++11编写的序列化方法,而不是json等,C++程序间使用

#pragma once
// ref: https://github.com/chanfun-ren/ChanfunRpc
// ref: https://my.oschina.net/u/3312209/blog/4313738

#include <vector>
#include <sstream>
#include <algorithm>
#include <cstdint>
#include <utility>
#include <tuple>
#include <type_traits>


// ref:https://stackoverflow.com/questions/25123458/is-trivially-copyable-is-not-a-member-of-std
#if (__GNUG__ && __GNUC__ < 5) || __cplusplus < 201402L // for C++11
// ref https://zhuanlan.zhihu.com/p/27186999
namespace std14 {
    template <class T, T...Ints>
    class integer_sequence {
    public:
        using value_type = T;
        static_assert(std::is_integral<value_type>::value,
            "not integral type");
        static constexpr std::size_t size() noexcept {
            return sizeof...(Ints);
        }
    };
    template <std::size_t...Inds>
    using index_sequence = integer_sequence<std::size_t, Inds...>;

    namespace Detail_ {

        template <class T, T Begin, T End, bool>
        struct IntSeqImpl {
            using TValue = T;
            static_assert(std::is_integral<TValue>::value,
                "not integral type");
            static_assert(Begin >= 0 && Begin < End,
                "unexpected argument (Begin<0 || Begin<=End)");

            template <class, class>
            struct IntSeqCombiner;

            template <TValue...Inds0, TValue...Inds1>
            struct IntSeqCombiner<integer_sequence<TValue, Inds0...>,
                integer_sequence<TValue, Inds1...>> {
                using TResult = integer_sequence<TValue, Inds0..., Inds1...>;
            };

            using TResult = typename IntSeqCombiner
                <typename IntSeqImpl<TValue, Begin, Begin + (End - Begin) / 2,
                (End - Begin) / 2 == 1>::TResult,
                typename IntSeqImpl<TValue, Begin + (End - Begin) / 2, End,
                (End - Begin + 1) / 2 == 1>::TResult>
                ::TResult;
        };

        template <class T, T Begin>
        struct IntSeqImpl<T, Begin, Begin, false> {
            using TValue = T;
            static_assert(std::is_integral<TValue>::value,
                "not integral type");
            static_assert(Begin >= 0, "unexpected argument (Begin<0)");
            using TResult = integer_sequence<TValue>;
        };

        template <class T, T Begin, T End>
        struct IntSeqImpl<T, Begin, End, true> {
            using TValue = T;
            static_assert(std::is_integral<TValue>::value,
                "not integral type");
            static_assert(Begin >= 0, "unexpected argument (Begin<0)");
            using TResult = integer_sequence<TValue, Begin>;
        };
    }

    template <class T, T N>
    using make_integer_sequence =
        typename Detail_::IntSeqImpl<T, 0, N, (N - 0) == 1>::TResult;

    template <std::size_t N>
    using make_index_sequence = make_integer_sequence<std::size_t, N>;

    template<class... T>
    using index_sequence_for = make_index_sequence<sizeof...(T)>;
}
///
    #define IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
    #define MAKE_INDEX_SEQUENCE std14::make_index_sequence
    #define INDEX_SEQUENCE std14::index_sequence
#else
    #define IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
    #define MAKE_INDEX_SEQUENCE std::make_index_sequence
    #define INDEX_SEQUENCE std::index_sequence
#endif

// 可平凡复制 
template <typename T, typename std::enable_if<IS_TRIVIALLY_COPYABLE(T), int>::type N = 0>
void serialize(std::ostream & os, const T & val)  { 
    os.write((const char *)&val,sizeof(T)); 
} 

// pair
template <typename K, typename V>
void serialize(std::ostream & os, const std::pair<K, V> & val) {
    serialize(os, val.first);
    serialize(os, val.second);
}

// std::string
void serialize(std::ostream & os, const std::string &val) {
    size_t size = val.size();
    os.write((const char *)&size, sizeof(size));
    os.write((const char *)val.data(), size * sizeof(typename std::string::value_type));
}

//容器 
template <typename T, typename std::enable_if< std::is_same<typename std::iterator_traits<typename T::iterator>::value_type, typename T::value_type>::value
    , int>::type N = 0> 
void serialize(std::ostream & os, const T & val) {
    size_t size = val.size();
    os.write((const char *)&size, sizeof(size_t));
    for (auto & v : val) {
        serialize(os, v); 
    } 
}


// tuple
template<typename T>
int _Serialize(std::ostream & os, T& val) {
    serialize(os, val);
    return 0;
}

template<typename Tuple, std::size_t... I>
void _Serialize(std::ostream & os, Tuple& tup, INDEX_SEQUENCE<I...>) {
    std::initializer_list<int>{_Serialize(os, std::get<I>(tup))...};
}


template <typename...Args>
void serialize(std::ostream & os, const std::tuple<Args...>& val) {
    _Serialize(os, val, MAKE_INDEX_SEQUENCE<sizeof...(Args)>{});
}


/*************************************** 反序列化 ***************************************/

// 可平凡复制 
template <typename T,typename std::enable_if<IS_TRIVIALLY_COPYABLE(T), int>::type N = 0>
void deserialize(std::istream & is, T & val) { 
     is.read((char *)&val, sizeof(T)); 
}

// std::string
void deserialize(std::istream & is, std::string &val) {
    size_t size = 0; 
    is.read((char*)&size, sizeof(size_t));
    val.resize(size);
    auto count = size * sizeof(typename std::string::value_type);
    is.read((char *)val.data(), count);
}


//pair
template <typename V>
struct ImpDeserialize {
    template<typename T>
    static void get(std::istream & is, T & val) {
        size_t size = 0;
        is.read((char *)&size, sizeof(size_t));
        for (size_t i = 0; i < size; i++)
        {
            V v;
            deserialize(is, v);
            val.insert(val.end(), v);
        }
    }
};

template <typename K, typename V>
struct ImpDeserialize<std::pair<K, V>> {
    template<typename T>
    static void get(std::istream & is, T & val) {
        size_t size = 0;
        is.read((char *)&size, sizeof(size_t));
        for (size_t i = 0; i < size; i++) {
            K k;
            V v;
            deserialize(is, k);
            deserialize(is, v);
            val.emplace(k, v);
        }
        
    }
};

// 容器 
template <typename T, typename std::enable_if< std::is_same<typename std::iterator_traits<typename T::iterator>::value_type, typename T::value_type>::value
    , int>::type N = 0>
void deserialize(std::istream & is, T & val) {
    ImpDeserialize<typename  T::value_type>::get(is, val);
}


//tuple
template<typename T>
int _Deserialize(std::istream & is, T& val) {
    deserialize(is, val);
    return 0;
}

template<typename Tuple, std::size_t... I>
void _Deserialize(std::istream & is, Tuple& tup, INDEX_SEQUENCE<I...>) {
    std::initializer_list<int>{_Deserialize(is, std::get<I>(tup))...};
}


template <typename...Args>
void deserialize(std::istream & is, std::tuple<Args...>& val) {
    _Deserialize(is, val, MAKE_INDEX_SEQUENCE<sizeof...(Args)>{});
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

橘色的喵

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

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

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

打赏作者

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

抵扣说明:

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

余额充值