仓库代码地址: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)>{});
}