mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
Merge branch 4.x
This commit is contained in:
@@ -110,8 +110,6 @@ if(MSVC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_definitions(-DDISABLE_OPENCV_24_COMPATIBILITY=1) # Avoid C-like legacy API
|
||||
|
||||
if(OPENCV_EXAMPLES_DISABLE_THREADS)
|
||||
# nothing
|
||||
elseif(MSVC OR APPLE)
|
||||
@@ -120,6 +118,7 @@ else()
|
||||
find_package(Threads)
|
||||
endif()
|
||||
if((TARGET Threads::Threads OR HAVE_THREADS) AND NOT OPENCV_EXAMPLES_DISABLE_THREADS)
|
||||
set(HAVE_THREADS 1)
|
||||
add_definitions(-DHAVE_THREADS=1)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ IF %ERRORLEVEL% EQU 0 (
|
||||
GOTO :PYTHON_FOUND
|
||||
)
|
||||
|
||||
CALL :QUERY_PYTHON 3.10
|
||||
IF %ERRORLEVEL% EQU 0 GOTO :PYTHON_FOUND
|
||||
CALL :QUERY_PYTHON 3.9
|
||||
IF %ERRORLEVEL% EQU 0 GOTO :PYTHON_FOUND
|
||||
CALL :QUERY_PYTHON 3.8
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
// This sample is based on "Camera calibration With OpenCV" tutorial:
|
||||
// https://docs.opencv.org/3.4/d4/d94/tutorial_camera_calibration.html
|
||||
// https://docs.opencv.org/5.x/d4/d94/tutorial_camera_calibration.html
|
||||
//
|
||||
// It uses standard OpenCV asymmetric circles grid pattern 11x4:
|
||||
// https://github.com/opencv/opencv/blob/3.4/doc/acircles_pattern.png
|
||||
// https://github.com/opencv/opencv/blob/5.x/doc/acircles_pattern.png
|
||||
// The results are the camera matrix and 5 distortion coefficients.
|
||||
//
|
||||
// Tap on highlighted pattern to capture pattern corners for calibration.
|
||||
|
||||
@@ -58,6 +58,7 @@ foreach(sample_filename ${cpp_samples})
|
||||
endif()
|
||||
if(HAVE_OPENGL AND sample_filename MATCHES "detect_mser")
|
||||
target_compile_definitions(${tgt} PRIVATE HAVE_OPENGL)
|
||||
ocv_target_link_libraries(${tgt} PRIVATE "${OPENGL_LIBRARIES}")
|
||||
endif()
|
||||
if(sample_filename MATCHES "simd_")
|
||||
# disabled intentionally - demonstration purposes only
|
||||
@@ -74,6 +75,8 @@ include("tutorial_code/calib3d/real_time_pose_estimation/CMakeLists.txt" OPTIONA
|
||||
if(OpenCV_FOUND AND NOT CMAKE_VERSION VERSION_LESS "3.1")
|
||||
add_subdirectory("example_cmake")
|
||||
endif()
|
||||
if(OpenCV_FOUND AND NOT CMAKE_VERSION VERSION_LESS "3.9")
|
||||
if(OpenCV_FOUND AND NOT CMAKE_VERSION VERSION_LESS "3.9"
|
||||
AND NOT OPENCV_EXAMPLES_SKIP_PARALLEL_BACKEND
|
||||
)
|
||||
add_subdirectory("tutorial_code/core/parallel_backend")
|
||||
endif()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -126,7 +126,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// These descriptors are going to be detecting and computing BLOBS with 6 different params
|
||||
// Param for first BLOB detector we want all
|
||||
typeDesc.push_back("BLOB"); // see http://docs.opencv.org/master/d0/d7a/classcv_1_1SimpleBlobDetector.html
|
||||
typeDesc.push_back("BLOB"); // see http://docs.opencv.org/5.x/d0/d7a/classcv_1_1SimpleBlobDetector.html
|
||||
pBLOB.push_back(pDefaultBLOB);
|
||||
pBLOB.back().filterByArea = true;
|
||||
pBLOB.back().minArea = 1;
|
||||
|
||||
@@ -89,10 +89,10 @@ static void help(char** argv)
|
||||
"\tThis will detect only the face in image.jpg.\n";
|
||||
|
||||
cout << " \n\nThe classifiers for face and eyes can be downloaded from : "
|
||||
" \nhttps://github.com/opencv/opencv/tree/master/data/haarcascades";
|
||||
" \nhttps://github.com/opencv/opencv/tree/5.x/data/haarcascades";
|
||||
|
||||
cout << "\n\nThe classifiers for nose and mouth can be downloaded from : "
|
||||
" \nhttps://github.com/opencv/opencv_contrib/tree/master/modules/face/data/cascades\n";
|
||||
" \nhttps://github.com/opencv/opencv_contrib/tree/5.x/modules/face/data/cascades\n";
|
||||
}
|
||||
|
||||
static void detectFaces(Mat& img, vector<Rect_<int> >& faces, string cascade_path)
|
||||
|
||||
@@ -16,14 +16,14 @@ struct ParamColorMap {
|
||||
String winName="False color";
|
||||
static const String ColorMaps[] = { "Autumn", "Bone", "Jet", "Winter", "Rainbow", "Ocean", "Summer", "Spring",
|
||||
"Cool", "HSV", "Pink", "Hot", "Parula", "Magma", "Inferno", "Plasma", "Viridis",
|
||||
"Cividis", "Twilight", "Twilight Shifted", "Turbo", "User defined (random)" };
|
||||
"Cividis", "Twilight", "Twilight Shifted", "Turbo", "Deep Green", "User defined (random)" };
|
||||
|
||||
static void TrackColorMap(int x, void *r)
|
||||
{
|
||||
ParamColorMap *p = (ParamColorMap*)r;
|
||||
Mat dst;
|
||||
p->iColormap= x;
|
||||
if (x == COLORMAP_TURBO + 1)
|
||||
if (x == COLORMAP_DEEPGREEN + 1)
|
||||
{
|
||||
Mat lutRND(256, 1, CV_8UC3);
|
||||
randu(lutRND, Scalar(0, 0, 0), Scalar(255, 255, 255));
|
||||
@@ -97,10 +97,10 @@ int main(int argc, char** argv)
|
||||
|
||||
imshow("Gray image",img);
|
||||
namedWindow(winName);
|
||||
createTrackbar("colormap", winName,&p.iColormap,1,TrackColorMap,(void*)&p);
|
||||
createTrackbar("colormap", winName, NULL, COLORMAP_DEEPGREEN + 1, TrackColorMap, (void*)&p);
|
||||
setTrackbarMin("colormap", winName, COLORMAP_AUTUMN);
|
||||
setTrackbarMax("colormap", winName, COLORMAP_TURBO+1);
|
||||
setTrackbarPos("colormap", winName, -1);
|
||||
setTrackbarMax("colormap", winName, COLORMAP_DEEPGREEN + 1);
|
||||
setTrackbarPos("colormap", winName, COLORMAP_AUTUMN);
|
||||
|
||||
TrackColorMap(0, (void*)&p);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ int main( int argc, const char** argv )
|
||||
|
||||
cout << "This program demonstrates the use of template matching with mask." << endl
|
||||
<< endl
|
||||
<< "Available methods: https://docs.opencv.org/master/df/dfb/group__imgproc__object.html#ga3a7850640f1fe1f58fe91a2d7583695d" << endl
|
||||
<< "Available methods: https://docs.opencv.org/5.x/df/dfb/group__imgproc__object.html#ga3a7850640f1fe1f58fe91a2d7583695d" << endl
|
||||
<< " TM_SQDIFF = " << (int)TM_SQDIFF << endl
|
||||
<< " TM_SQDIFF_NORMED = " << (int)TM_SQDIFF_NORMED << endl
|
||||
<< " TM_CCORR = " << (int)TM_CCORR << endl
|
||||
|
||||
@@ -24,11 +24,11 @@ int main(int argc, char *argv[])
|
||||
vector<String> typeAlgoMatch;
|
||||
vector<String> fileName;
|
||||
// This descriptor are going to be detect and compute
|
||||
typeDesc.push_back("AKAZE-DESCRIPTOR_KAZE_UPRIGHT"); // see https://docs.opencv.org/master/d8/d30/classcv_1_1AKAZE.html
|
||||
typeDesc.push_back("AKAZE"); // see http://docs.opencv.org/master/d8/d30/classcv_1_1AKAZE.html
|
||||
typeDesc.push_back("ORB"); // see http://docs.opencv.org/master/de/dbf/classcv_1_1BRISK.html
|
||||
typeDesc.push_back("BRISK"); // see http://docs.opencv.org/master/db/d95/classcv_1_1ORB.html
|
||||
// This algorithm would be used to match descriptors see http://docs.opencv.org/master/db/d39/classcv_1_1DescriptorMatcher.html#ab5dc5036569ecc8d47565007fa518257
|
||||
typeDesc.push_back("AKAZE-DESCRIPTOR_KAZE_UPRIGHT"); // see https://docs.opencv.org/5.x/d8/d30/classcv_1_1AKAZE.html
|
||||
typeDesc.push_back("AKAZE"); // see http://docs.opencv.org/5.x/d8/d30/classcv_1_1AKAZE.html
|
||||
typeDesc.push_back("ORB"); // see http://docs.opencv.org/5.x/de/dbf/classcv_1_1BRISK.html
|
||||
typeDesc.push_back("BRISK"); // see http://docs.opencv.org/5.x/db/d95/classcv_1_1ORB.html
|
||||
// This algorithm would be used to match descriptors see http://docs.opencv.org/5.x/db/d39/classcv_1_1DescriptorMatcher.html#ab5dc5036569ecc8d47565007fa518257
|
||||
typeAlgoMatch.push_back("BruteForce");
|
||||
typeAlgoMatch.push_back("BruteForce-L1");
|
||||
typeAlgoMatch.push_back("BruteForce-Hamming");
|
||||
|
||||
@@ -2,25 +2,36 @@ cmake_minimum_required(VERSION 3.9)
|
||||
|
||||
find_package(OpenCV REQUIRED COMPONENTS opencv_core)
|
||||
|
||||
find_package(OpenMP)
|
||||
if(OpenMP_FOUND)
|
||||
project(opencv_example_openmp_backend)
|
||||
add_executable(opencv_example_openmp_backend example-openmp.cpp)
|
||||
target_link_libraries(opencv_example_openmp_backend PRIVATE
|
||||
opencv_core
|
||||
OpenMP::OpenMP_CXX
|
||||
)
|
||||
if(NOT OPENCV_EXAMPLES_SKIP_PARALLEL_BACKEND_OPENMP
|
||||
AND NOT OPENCV_EXAMPLES_SKIP_OPENMP
|
||||
)
|
||||
find_package(OpenMP)
|
||||
if(OpenMP_FOUND)
|
||||
project(opencv_example_openmp_backend)
|
||||
add_executable(opencv_example_openmp_backend example-openmp.cpp)
|
||||
target_link_libraries(opencv_example_openmp_backend PRIVATE
|
||||
opencv_core
|
||||
OpenMP::OpenMP_CXX
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# TODO: find_package(TBB)
|
||||
find_path(TBB_INCLUDE_DIR NAMES "tbb/tbb.h")
|
||||
find_library(TBB_LIBRARY NAMES "tbb")
|
||||
if(TBB_INCLUDE_DIR AND TBB_LIBRARY AND NOT OPENCV_EXAMPLE_SKIP_TBB)
|
||||
project(opencv_example_tbb_backend)
|
||||
add_executable(opencv_example_tbb_backend example-tbb.cpp)
|
||||
target_include_directories(opencv_example_tbb_backend SYSTEM PRIVATE ${TBB_INCLUDE_DIR})
|
||||
target_link_libraries(opencv_example_tbb_backend PRIVATE
|
||||
opencv_core
|
||||
${TBB_LIBRARY}
|
||||
)
|
||||
if(NOT OPENCV_EXAMPLES_SKIP_PARALLEL_BACKEND_TBB
|
||||
AND NOT OPENCV_EXAMPLES_SKIP_TBB
|
||||
AND NOT OPENCV_EXAMPLE_SKIP_TBB # deprecated (to be removed in OpenCV 5.0)
|
||||
)
|
||||
find_package(TBB QUIET)
|
||||
if(NOT TBB_FOUND)
|
||||
find_path(TBB_INCLUDE_DIR NAMES "tbb/tbb.h")
|
||||
find_library(TBB_LIBRARY NAMES "tbb")
|
||||
endif()
|
||||
if(TBB_INCLUDE_DIR AND TBB_LIBRARY)
|
||||
project(opencv_example_tbb_backend)
|
||||
add_executable(opencv_example_tbb_backend example-tbb.cpp)
|
||||
target_include_directories(opencv_example_tbb_backend SYSTEM PRIVATE ${TBB_INCLUDE_DIR})
|
||||
target_link_libraries(opencv_example_tbb_backend PRIVATE
|
||||
opencv_core
|
||||
${TBB_LIBRARY}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/gapi.hpp>
|
||||
#include <opencv2/gapi/core.hpp>
|
||||
#include <opencv2/gapi/imgproc.hpp>
|
||||
|
||||
#include <opencv2/gapi/s11n.hpp>
|
||||
#include <opencv2/gapi/garg.hpp>
|
||||
#include <opencv2/gapi/gcommon.hpp>
|
||||
|
||||
#include <opencv2/gapi/cpu/gcpukernel.hpp>
|
||||
|
||||
#include <opencv2/gapi/fluid/core.hpp>
|
||||
#include <opencv2/gapi/fluid/imgproc.hpp>
|
||||
|
||||
static void gscalar_example()
|
||||
{
|
||||
//! [gscalar_implicit]
|
||||
cv::GMat a;
|
||||
cv::GMat b = a + 1;
|
||||
//! [gscalar_implicit]
|
||||
}
|
||||
|
||||
static void typed_example()
|
||||
{
|
||||
const cv::Size sz(32, 32);
|
||||
cv::Mat
|
||||
in_mat1 (sz, CV_8UC1),
|
||||
in_mat2 (sz, CV_8UC1),
|
||||
out_mat_untyped(sz, CV_8UC1),
|
||||
out_mat_typed1 (sz, CV_8UC1),
|
||||
out_mat_typed2 (sz, CV_8UC1);
|
||||
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
|
||||
//! [Untyped_Example]
|
||||
// Untyped G-API ///////////////////////////////////////////////////////////
|
||||
cv::GComputation cvtU([]()
|
||||
{
|
||||
cv::GMat in1, in2;
|
||||
cv::GMat out = cv::gapi::add(in1, in2);
|
||||
return cv::GComputation({in1, in2}, {out});
|
||||
});
|
||||
std::vector<cv::Mat> u_ins = {in_mat1, in_mat2};
|
||||
std::vector<cv::Mat> u_outs = {out_mat_untyped};
|
||||
cvtU.apply(u_ins, u_outs);
|
||||
//! [Untyped_Example]
|
||||
|
||||
//! [Typed_Example]
|
||||
// Typed G-API /////////////////////////////////////////////////////////////
|
||||
cv::GComputationT<cv::GMat (cv::GMat, cv::GMat)> cvtT([](cv::GMat m1, cv::GMat m2)
|
||||
{
|
||||
return m1+m2;
|
||||
});
|
||||
cvtT.apply(in_mat1, in_mat2, out_mat_typed1);
|
||||
|
||||
auto cvtTC = cvtT.compile(cv::descr_of(in_mat1), cv::descr_of(in_mat2));
|
||||
cvtTC(in_mat1, in_mat2, out_mat_typed2);
|
||||
//! [Typed_Example]
|
||||
}
|
||||
|
||||
static void bind_serialization_example()
|
||||
{
|
||||
// ! [bind after deserialization]
|
||||
cv::GCompiled compd;
|
||||
std::vector<char> bytes;
|
||||
auto graph = cv::gapi::deserialize<cv::GComputation>(bytes);
|
||||
auto meta = cv::gapi::deserialize<cv::GMetaArgs>(bytes);
|
||||
|
||||
compd = graph.compile(std::move(meta), cv::compile_args());
|
||||
auto in_args = cv::gapi::deserialize<cv::GRunArgs>(bytes);
|
||||
auto out_args = cv::gapi::deserialize<cv::GRunArgs>(bytes);
|
||||
compd(std::move(in_args), cv::gapi::bind(out_args));
|
||||
// ! [bind after deserialization]
|
||||
}
|
||||
|
||||
static void bind_deserialization_example()
|
||||
{
|
||||
// ! [bind before serialization]
|
||||
std::vector<cv::GRunArgP> graph_outs;
|
||||
cv::GRunArgs out_args;
|
||||
|
||||
for (auto &&out : graph_outs) {
|
||||
out_args.emplace_back(cv::gapi::bind(out));
|
||||
}
|
||||
const auto sargsout = cv::gapi::serialize(out_args);
|
||||
// ! [bind before serialization]
|
||||
}
|
||||
|
||||
struct SimpleCustomType {
|
||||
bool val;
|
||||
bool operator==(const SimpleCustomType& other) const {
|
||||
return val == other.val;
|
||||
}
|
||||
};
|
||||
|
||||
struct SimpleCustomType2 {
|
||||
int val;
|
||||
std::string name;
|
||||
std::vector<float> vec;
|
||||
std::map<int, uint64_t> mmap;
|
||||
bool operator==(const SimpleCustomType2& other) const {
|
||||
return val == other.val && name == other.name &&
|
||||
vec == other.vec && mmap == other.mmap;
|
||||
}
|
||||
};
|
||||
|
||||
// ! [S11N usage]
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
namespace s11n {
|
||||
namespace detail {
|
||||
template<> struct S11N<SimpleCustomType> {
|
||||
static void serialize(IOStream &os, const SimpleCustomType &p) {
|
||||
os << p.val;
|
||||
}
|
||||
static SimpleCustomType deserialize(IIStream &is) {
|
||||
SimpleCustomType p;
|
||||
is >> p.val;
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct S11N<SimpleCustomType2> {
|
||||
static void serialize(IOStream &os, const SimpleCustomType2 &p) {
|
||||
os << p.val << p.name << p.vec << p.mmap;
|
||||
}
|
||||
static SimpleCustomType2 deserialize(IIStream &is) {
|
||||
SimpleCustomType2 p;
|
||||
is >> p.val >> p.name >> p.vec >> p.mmap;
|
||||
return p;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace s11n
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
// ! [S11N usage]
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
template<> struct CompileArgTag<SimpleCustomType> {
|
||||
static const char* tag() {
|
||||
return "org.opencv.test.simple_custom_type";
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct CompileArgTag<SimpleCustomType2> {
|
||||
static const char* tag() {
|
||||
return "org.opencv.test.simple_custom_type_2";
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace cv
|
||||
|
||||
static void s11n_example()
|
||||
{
|
||||
SimpleCustomType customVar1 { false };
|
||||
SimpleCustomType2 customVar2 { 1248, "World", {1280, 720, 640, 480},
|
||||
{ {5, 32434142342}, {7, 34242432} } };
|
||||
|
||||
std::vector<char> sArgs = cv::gapi::serialize(
|
||||
cv::compile_args(customVar1, customVar2));
|
||||
|
||||
cv::GCompileArgs dArgs = cv::gapi::deserialize<cv::GCompileArgs,
|
||||
SimpleCustomType,
|
||||
SimpleCustomType2>(sArgs);
|
||||
|
||||
SimpleCustomType dCustomVar1 = cv::gapi::getCompileArg<SimpleCustomType>(dArgs).value();
|
||||
SimpleCustomType2 dCustomVar2 = cv::gapi::getCompileArg<SimpleCustomType2>(dArgs).value();
|
||||
|
||||
(void) dCustomVar1;
|
||||
(void) dCustomVar2;
|
||||
}
|
||||
|
||||
G_TYPED_KERNEL(IAdd, <cv::GMat(cv::GMat)>, "test.custom.add") {
|
||||
static cv::GMatDesc outMeta(const cv::GMatDesc &in) { return in; }
|
||||
};
|
||||
G_TYPED_KERNEL(IFilter2D, <cv::GMat(cv::GMat)>, "test.custom.filter2d") {
|
||||
static cv::GMatDesc outMeta(const cv::GMatDesc &in) { return in; }
|
||||
};
|
||||
G_TYPED_KERNEL(IRGB2YUV, <cv::GMat(cv::GMat)>, "test.custom.add") {
|
||||
static cv::GMatDesc outMeta(const cv::GMatDesc &in) { return in; }
|
||||
};
|
||||
GAPI_OCV_KERNEL(CustomAdd, IAdd) { static void run(cv::Mat, cv::Mat &) {} };
|
||||
GAPI_OCV_KERNEL(CustomFilter2D, IFilter2D) { static void run(cv::Mat, cv::Mat &) {} };
|
||||
GAPI_OCV_KERNEL(CustomRGB2YUV, IRGB2YUV) { static void run(cv::Mat, cv::Mat &) {} };
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 3)
|
||||
return -1;
|
||||
|
||||
cv::Mat input = cv::imread(argv[1]);
|
||||
cv::Mat output;
|
||||
|
||||
{
|
||||
//! [graph_def]
|
||||
cv::GMat in;
|
||||
cv::GMat gx = cv::gapi::Sobel(in, CV_32F, 1, 0);
|
||||
cv::GMat gy = cv::gapi::Sobel(in, CV_32F, 0, 1);
|
||||
cv::GMat g = cv::gapi::sqrt(cv::gapi::mul(gx, gx) + cv::gapi::mul(gy, gy));
|
||||
cv::GMat out = cv::gapi::convertTo(g, CV_8U);
|
||||
//! [graph_def]
|
||||
|
||||
//! [graph_decl_apply]
|
||||
//! [graph_cap_full]
|
||||
cv::GComputation sobelEdge(cv::GIn(in), cv::GOut(out));
|
||||
//! [graph_cap_full]
|
||||
sobelEdge.apply(input, output);
|
||||
//! [graph_decl_apply]
|
||||
|
||||
//! [apply_with_param]
|
||||
cv::GKernelPackage kernels = cv::gapi::combine
|
||||
(cv::gapi::core::fluid::kernels(),
|
||||
cv::gapi::imgproc::fluid::kernels());
|
||||
sobelEdge.apply(input, output, cv::compile_args(kernels));
|
||||
//! [apply_with_param]
|
||||
|
||||
//! [graph_cap_sub]
|
||||
cv::GComputation sobelEdgeSub(cv::GIn(gx, gy), cv::GOut(out));
|
||||
//! [graph_cap_sub]
|
||||
}
|
||||
//! [graph_gen]
|
||||
cv::GComputation sobelEdgeGen([](){
|
||||
cv::GMat in;
|
||||
cv::GMat gx = cv::gapi::Sobel(in, CV_32F, 1, 0);
|
||||
cv::GMat gy = cv::gapi::Sobel(in, CV_32F, 0, 1);
|
||||
cv::GMat g = cv::gapi::sqrt(cv::gapi::mul(gx, gx) + cv::gapi::mul(gy, gy));
|
||||
cv::GMat out = cv::gapi::convertTo(g, CV_8U);
|
||||
return cv::GComputation(in, out);
|
||||
});
|
||||
//! [graph_gen]
|
||||
|
||||
cv::imwrite(argv[2], output);
|
||||
|
||||
//! [kernels_snippet]
|
||||
cv::GKernelPackage pkg = cv::gapi::kernels
|
||||
< CustomAdd
|
||||
, CustomFilter2D
|
||||
, CustomRGB2YUV
|
||||
>();
|
||||
//! [kernels_snippet]
|
||||
|
||||
// Just call typed example with no input/output - avoid warnings about
|
||||
// unused functions
|
||||
typed_example();
|
||||
gscalar_example();
|
||||
bind_serialization_example();
|
||||
bind_deserialization_example();
|
||||
s11n_example();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <opencv2/gapi.hpp>
|
||||
#include <opencv2/gapi/cpu/imgproc.hpp>
|
||||
#include <opencv2/gapi/imgproc.hpp>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
bool need_first_conversion = true;
|
||||
bool need_second_conversion = false;
|
||||
|
||||
cv::Size szOut(4, 4);
|
||||
cv::GComputation cc([&](){
|
||||
// ! [GIOProtoArgs usage]
|
||||
auto ins = cv::GIn();
|
||||
cv::GMat in1;
|
||||
if (need_first_conversion)
|
||||
ins += cv::GIn(in1);
|
||||
|
||||
cv::GMat in2;
|
||||
if (need_second_conversion)
|
||||
ins += cv::GIn(in2);
|
||||
|
||||
auto outs = cv::GOut();
|
||||
cv::GMat out1 = cv::gapi::resize(in1, szOut);
|
||||
if (need_first_conversion)
|
||||
outs += cv::GOut(out1);
|
||||
|
||||
cv::GMat out2 = cv::gapi::resize(in2, szOut);
|
||||
if (need_second_conversion)
|
||||
outs += cv::GOut(out2);
|
||||
// ! [GIOProtoArgs usage]
|
||||
return cv::GComputation(std::move(ins), std::move(outs));
|
||||
});
|
||||
|
||||
// ! [GRunArgs usage]
|
||||
auto in_vector = cv::gin();
|
||||
|
||||
cv::Mat in_mat1( 8, 8, CV_8UC3);
|
||||
cv::Mat in_mat2(16, 16, CV_8UC3);
|
||||
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
|
||||
if (need_first_conversion)
|
||||
in_vector += cv::gin(in_mat1);
|
||||
if (need_second_conversion)
|
||||
in_vector += cv::gin(in_mat2);
|
||||
// ! [GRunArgs usage]
|
||||
|
||||
// ! [GRunArgsP usage]
|
||||
auto out_vector = cv::gout();
|
||||
cv::Mat out_mat1, out_mat2;
|
||||
if (need_first_conversion)
|
||||
out_vector += cv::gout(out_mat1);
|
||||
if (need_second_conversion)
|
||||
out_vector += cv::gout(out_mat2);
|
||||
// ! [GRunArgsP usage]
|
||||
|
||||
auto stream = cc.compileStreaming(cv::compile_args(cv::gapi::imgproc::cpu::kernels()));
|
||||
stream.setSource(std::move(in_vector));
|
||||
|
||||
stream.start();
|
||||
stream.pull(std::move(out_vector));
|
||||
stream.stop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// [filter2d_api]
|
||||
#include <opencv2/gapi.hpp>
|
||||
|
||||
G_TYPED_KERNEL(GFilter2D,
|
||||
<cv::GMat(cv::GMat,int,cv::Mat,cv::Point,double,int,cv::Scalar)>,
|
||||
"org.opencv.imgproc.filters.filter2D")
|
||||
{
|
||||
static cv::GMatDesc // outMeta's return value type
|
||||
outMeta(cv::GMatDesc in , // descriptor of input GMat
|
||||
int ddepth , // depth parameter
|
||||
cv::Mat /* coeffs */, // (unused)
|
||||
cv::Point /* anchor */, // (unused)
|
||||
double /* scale */, // (unused)
|
||||
int /* border */, // (unused)
|
||||
cv::Scalar /* bvalue */ ) // (unused)
|
||||
{
|
||||
return in.withDepth(ddepth);
|
||||
}
|
||||
};
|
||||
// [filter2d_api]
|
||||
|
||||
cv::GMat filter2D(cv::GMat ,
|
||||
int ,
|
||||
cv::Mat ,
|
||||
cv::Point ,
|
||||
double ,
|
||||
int ,
|
||||
cv::Scalar);
|
||||
|
||||
// [filter2d_wrap]
|
||||
cv::GMat filter2D(cv::GMat in,
|
||||
int ddepth,
|
||||
cv::Mat k,
|
||||
cv::Point anchor = cv::Point(-1,-1),
|
||||
double scale = 0.,
|
||||
int border = cv::BORDER_DEFAULT,
|
||||
cv::Scalar bval = cv::Scalar(0))
|
||||
{
|
||||
return GFilter2D::on(in, ddepth, k, anchor, scale, border, bval);
|
||||
}
|
||||
// [filter2d_wrap]
|
||||
|
||||
// [compound]
|
||||
#include <opencv2/gapi/gcompoundkernel.hpp> // GAPI_COMPOUND_KERNEL()
|
||||
|
||||
using PointArray2f = cv::GArray<cv::Point2f>;
|
||||
|
||||
G_TYPED_KERNEL(HarrisCorners,
|
||||
<PointArray2f(cv::GMat,int,double,double,int,double)>,
|
||||
"org.opencv.imgproc.harris_corner")
|
||||
{
|
||||
static cv::GArrayDesc outMeta(const cv::GMatDesc &,
|
||||
int,
|
||||
double,
|
||||
double,
|
||||
int,
|
||||
double)
|
||||
{
|
||||
// No special metadata for arrays in G-API (yet)
|
||||
return cv::empty_array_desc();
|
||||
}
|
||||
};
|
||||
|
||||
// Define Fluid-backend-local kernels which form GoodFeatures
|
||||
G_TYPED_KERNEL(HarrisResponse,
|
||||
<cv::GMat(cv::GMat,double,int,double)>,
|
||||
"org.opencv.fluid.harris_response")
|
||||
{
|
||||
static cv::GMatDesc outMeta(const cv::GMatDesc &in,
|
||||
double,
|
||||
int,
|
||||
double)
|
||||
{
|
||||
return in.withType(CV_32F, 1);
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(ArrayNMS,
|
||||
<PointArray2f(cv::GMat,int,double)>,
|
||||
"org.opencv.cpu.nms_array")
|
||||
{
|
||||
static cv::GArrayDesc outMeta(const cv::GMatDesc &,
|
||||
int,
|
||||
double)
|
||||
{
|
||||
return cv::empty_array_desc();
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_COMPOUND_KERNEL(GFluidHarrisCorners, HarrisCorners)
|
||||
{
|
||||
static PointArray2f
|
||||
expand(cv::GMat in,
|
||||
int maxCorners,
|
||||
double quality,
|
||||
double minDist,
|
||||
int blockSize,
|
||||
double k)
|
||||
{
|
||||
cv::GMat response = HarrisResponse::on(in, quality, blockSize, k);
|
||||
return ArrayNMS::on(response, maxCorners, minDist);
|
||||
}
|
||||
};
|
||||
|
||||
// Then implement HarrisResponse as Fluid kernel and NMSresponse
|
||||
// as a generic (OpenCV) kernel
|
||||
// [compound]
|
||||
|
||||
// [filter2d_ocv]
|
||||
#include <opencv2/gapi/cpu/gcpukernel.hpp> // GAPI_OCV_KERNEL()
|
||||
#include <opencv2/imgproc.hpp> // cv::filter2D()
|
||||
|
||||
GAPI_OCV_KERNEL(GCPUFilter2D, GFilter2D)
|
||||
{
|
||||
static void
|
||||
run(const cv::Mat &in, // in - derived from GMat
|
||||
const int ddepth, // opaque (passed as-is)
|
||||
const cv::Mat &k, // opaque (passed as-is)
|
||||
const cv::Point &anchor, // opaque (passed as-is)
|
||||
const double delta, // opaque (passed as-is)
|
||||
const int border, // opaque (passed as-is)
|
||||
const cv::Scalar &, // opaque (passed as-is)
|
||||
cv::Mat &out) // out - derived from GMat (retval)
|
||||
{
|
||||
cv::filter2D(in, out, ddepth, k, anchor, delta, border);
|
||||
}
|
||||
};
|
||||
// [filter2d_ocv]
|
||||
|
||||
int main(int, char *[])
|
||||
{
|
||||
std::cout << "This sample is non-complete. It is used as code snippents in documentation." << std::endl;
|
||||
|
||||
cv::Mat conv_kernel_mat;
|
||||
|
||||
{
|
||||
// [filter2d_on]
|
||||
cv::GMat in;
|
||||
cv::GMat out = GFilter2D::on(/* GMat */ in,
|
||||
/* int */ -1,
|
||||
/* Mat */ conv_kernel_mat,
|
||||
/* Point */ cv::Point(-1,-1),
|
||||
/* double */ 0.,
|
||||
/* int */ cv::BORDER_DEFAULT,
|
||||
/* Scalar */ cv::Scalar(0));
|
||||
// [filter2d_on]
|
||||
}
|
||||
|
||||
{
|
||||
// [filter2d_wrap_call]
|
||||
cv::GMat in;
|
||||
cv::GMat out = filter2D(in, -1, conv_kernel_mat);
|
||||
// [filter2d_wrap_call]
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -63,7 +63,7 @@ int main()
|
||||
//! [kernel_pkg_proper]
|
||||
//! [kernel_pkg]
|
||||
// Prepare the kernel package and run the graph
|
||||
cv::gapi::GKernelPackage fluid_kernels = cv::gapi::combine // Define a custom kernel package:
|
||||
cv::GKernelPackage fluid_kernels = cv::gapi::combine // Define a custom kernel package:
|
||||
(cv::gapi::core::fluid::kernels(), // ...with Fluid Core kernels
|
||||
cv::gapi::imgproc::fluid::kernels()); // ...and Fluid ImgProc kernels
|
||||
//! [kernel_pkg]
|
||||
|
||||
@@ -4,6 +4,17 @@
|
||||
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#if !defined(HAVE_THREADS)
|
||||
int main()
|
||||
{
|
||||
std::cout << "This sample is built without threading support. Sample code is disabled." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
@@ -200,3 +211,5 @@ int main()
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
CommandLineParser parser(argc, argv, "{@audio||}");
|
||||
string file = parser.get<string>("@audio");
|
||||
|
||||
if (file.empty())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
Mat frame;
|
||||
vector<vector<Mat>> audioData;
|
||||
VideoCapture cap;
|
||||
vector<int> params { CAP_PROP_AUDIO_STREAM, 0,
|
||||
CAP_PROP_VIDEO_STREAM, -1,
|
||||
CAP_PROP_AUDIO_DATA_DEPTH, CV_16S };
|
||||
|
||||
cap.open(file, CAP_MSMF, params);
|
||||
if (!cap.isOpened())
|
||||
{
|
||||
cerr << "ERROR! Can't to open file: " + file << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int audioBaseIndex = (int)cap.get(CAP_PROP_AUDIO_BASE_INDEX);
|
||||
const int numberOfChannels = (int)cap.get(CAP_PROP_AUDIO_TOTAL_CHANNELS);
|
||||
cout << "CAP_PROP_AUDIO_DATA_DEPTH: " << depthToString((int)cap.get(CAP_PROP_AUDIO_DATA_DEPTH)) << endl;
|
||||
cout << "CAP_PROP_AUDIO_SAMPLES_PER_SECOND: " << cap.get(CAP_PROP_AUDIO_SAMPLES_PER_SECOND) << endl;
|
||||
cout << "CAP_PROP_AUDIO_TOTAL_CHANNELS: " << numberOfChannels << endl;
|
||||
cout << "CAP_PROP_AUDIO_TOTAL_STREAMS: " << cap.get(CAP_PROP_AUDIO_TOTAL_STREAMS) << endl;
|
||||
|
||||
int numberOfSamples = 0;
|
||||
audioData.resize(numberOfChannels);
|
||||
for (;;)
|
||||
{
|
||||
if (cap.grab())
|
||||
{
|
||||
for (int nCh = 0; nCh < numberOfChannels; nCh++)
|
||||
{
|
||||
cap.retrieve(frame, audioBaseIndex+nCh);
|
||||
audioData[nCh].push_back(frame);
|
||||
numberOfSamples+=frame.cols;
|
||||
}
|
||||
}
|
||||
else { break; }
|
||||
}
|
||||
|
||||
cout << "Number of samples: " << numberOfSamples << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
cv::CommandLineParser parser(argc, argv, "{@audio||}");
|
||||
string file = parser.get<string>("@audio");
|
||||
|
||||
if (file.empty())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
Mat videoFrame;
|
||||
Mat audioFrame;
|
||||
vector<vector<Mat>> audioData;
|
||||
VideoCapture cap;
|
||||
vector<int> params { CAP_PROP_AUDIO_STREAM, 0,
|
||||
CAP_PROP_VIDEO_STREAM, 0,
|
||||
CAP_PROP_AUDIO_DATA_DEPTH, CV_16S };
|
||||
|
||||
cap.open(file, CAP_MSMF, params);
|
||||
if (!cap.isOpened())
|
||||
{
|
||||
cerr << "ERROR! Can't to open file: " + file << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int audioBaseIndex = (int)cap.get(CAP_PROP_AUDIO_BASE_INDEX);
|
||||
const int numberOfChannels = (int)cap.get(CAP_PROP_AUDIO_TOTAL_CHANNELS);
|
||||
cout << "CAP_PROP_AUDIO_DATA_DEPTH: " << depthToString((int)cap.get(CAP_PROP_AUDIO_DATA_DEPTH)) << endl;
|
||||
cout << "CAP_PROP_AUDIO_SAMPLES_PER_SECOND: " << cap.get(CAP_PROP_AUDIO_SAMPLES_PER_SECOND) << endl;
|
||||
cout << "CAP_PROP_AUDIO_TOTAL_CHANNELS: " << cap.get(CAP_PROP_AUDIO_TOTAL_CHANNELS) << endl;
|
||||
cout << "CAP_PROP_AUDIO_TOTAL_STREAMS: " << cap.get(CAP_PROP_AUDIO_TOTAL_STREAMS) << endl;
|
||||
|
||||
int numberOfSamples = 0;
|
||||
int numberOfFrames = 0;
|
||||
audioData.resize(numberOfChannels);
|
||||
for (;;)
|
||||
{
|
||||
if (cap.grab())
|
||||
{
|
||||
cap.retrieve(videoFrame);
|
||||
for (int nCh = 0; nCh < numberOfChannels; nCh++)
|
||||
{
|
||||
cap.retrieve(audioFrame, audioBaseIndex+nCh);
|
||||
if (!audioFrame.empty())
|
||||
audioData[nCh].push_back(audioFrame);
|
||||
numberOfSamples+=audioFrame.cols;
|
||||
}
|
||||
if (!videoFrame.empty())
|
||||
{
|
||||
numberOfFrames++;
|
||||
imshow("Live", videoFrame);
|
||||
if (waitKey(5) >= 0)
|
||||
break;
|
||||
}
|
||||
} else { break; }
|
||||
}
|
||||
|
||||
cout << "Number of audio samples: " << numberOfSamples << endl
|
||||
<< "Number of video frames: " << numberOfFrames << endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,352 +0,0 @@
|
||||
#include "opencv2/videoio.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
static bool g_printStreamSetting;
|
||||
static int g_imageStreamProfileIdx;
|
||||
static int g_depthStreamProfileIdx;
|
||||
static bool g_irStreamShow;
|
||||
static double g_imageBrightness;
|
||||
static double g_imageContrast;
|
||||
static bool g_printTiming;
|
||||
static bool g_showClosedPoint;
|
||||
|
||||
|
||||
static int g_closedDepthPoint[2];
|
||||
|
||||
static void printUsage(const char *arg0)
|
||||
{
|
||||
const char *filename = arg0;
|
||||
while (*filename)
|
||||
filename++;
|
||||
while ((arg0 <= filename) && ('\\' != *filename) && ('/' != *filename))
|
||||
filename--;
|
||||
filename++;
|
||||
|
||||
cout << "This program demonstrates usage of camera supported\nby Intel Perceptual computing SDK." << endl << endl;
|
||||
cout << "usage: " << filename << "[-ps] [-isp=IDX] [-dsp=IDX]\n [-ir] [-imb=VAL] [-imc=VAL]" << endl << endl;
|
||||
cout << " -ps, print streams setting and profiles" << endl;
|
||||
cout << " -isp=IDX, set profile index of the image stream" << endl;
|
||||
cout << " -dsp=IDX, set profile index of the depth stream" << endl;
|
||||
cout << " -ir, show data from IR stream" << endl;
|
||||
cout << " -imb=VAL, set brightness value for an image stream" << endl;
|
||||
cout << " -imc=VAL, set contrast value for a image stream" << endl;
|
||||
cout << " -pts, print frame index and frame time" << endl;
|
||||
cout << " --show-closed, print frame index and frame time" << endl;
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
static void parseCMDLine(int argc, char* argv[])
|
||||
{
|
||||
cv::CommandLineParser parser(argc, argv,
|
||||
"{ h help | | }"
|
||||
"{ ps print-streams | | }"
|
||||
"{ isp image-stream-prof | -1 | }"
|
||||
"{ dsp depth-stream-prof | -1 | }"
|
||||
"{ir||}{imb||}{imc||}{pts||}{show-closed||}");
|
||||
if (parser.has("h"))
|
||||
{
|
||||
printUsage(argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
g_printStreamSetting = parser.has("ps");
|
||||
g_imageStreamProfileIdx = parser.get<int>("isp");
|
||||
g_depthStreamProfileIdx = parser.get<int>("dsp");
|
||||
g_irStreamShow = parser.has("ir");
|
||||
if (parser.has("imb"))
|
||||
g_imageBrightness = parser.get<double>("imb");
|
||||
else
|
||||
g_imageBrightness = -DBL_MAX;
|
||||
if (parser.has("imc"))
|
||||
g_imageContrast = parser.get<double>("imc");
|
||||
else
|
||||
g_imageContrast = -DBL_MAX;
|
||||
g_printTiming = parser.has("pts");
|
||||
g_showClosedPoint = parser.has("show-closed");
|
||||
if (!parser.check())
|
||||
{
|
||||
parser.printErrors();
|
||||
exit(-1);
|
||||
}
|
||||
if (g_showClosedPoint && (-1 == g_depthStreamProfileIdx))
|
||||
{
|
||||
cerr << "For --show-closed depth profile has be selected" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static void printStreamProperties(VideoCapture &capture)
|
||||
{
|
||||
size_t profilesCount = (size_t)capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_INTELPERC_PROFILE_COUNT);
|
||||
cout << "Image stream." << endl;
|
||||
cout << " Brightness = " << capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_BRIGHTNESS) << endl;
|
||||
cout << " Contrast = " << capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_CONTRAST) << endl;
|
||||
cout << " Saturation = " << capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_SATURATION) << endl;
|
||||
cout << " Hue = " << capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_HUE) << endl;
|
||||
cout << " Gamma = " << capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_GAMMA) << endl;
|
||||
cout << " Sharpness = " << capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_SHARPNESS) << endl;
|
||||
cout << " Gain = " << capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_GAIN) << endl;
|
||||
cout << " Backligh = " << capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_BACKLIGHT) << endl;
|
||||
cout << "Image streams profiles:" << endl;
|
||||
for (size_t i = 0; i < profilesCount; i++)
|
||||
{
|
||||
capture.set(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_INTELPERC_PROFILE_IDX, (double)i);
|
||||
cout << " Profile[" << i << "]: ";
|
||||
cout << "width = " <<
|
||||
(int)capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_FRAME_WIDTH);
|
||||
cout << ", height = " <<
|
||||
(int)capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_FRAME_HEIGHT);
|
||||
cout << ", fps = " <<
|
||||
capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_FPS);
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
profilesCount = (size_t)capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_PROFILE_COUNT);
|
||||
cout << "Depth stream." << endl;
|
||||
cout << " Low confidence value = " << capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE) << endl;
|
||||
cout << " Saturation value = " << capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE) << endl;
|
||||
cout << " Confidence threshold = " << capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_DEPTH_CONFIDENCE_THRESHOLD) << endl;
|
||||
cout << " Focal length = (" << capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_HORZ) << ", "
|
||||
<< capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_VERT) << ")" << endl;
|
||||
cout << "Depth streams profiles:" << endl;
|
||||
for (size_t i = 0; i < profilesCount; i++)
|
||||
{
|
||||
capture.set(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_PROFILE_IDX, (double)i);
|
||||
cout << " Profile[" << i << "]: ";
|
||||
cout << "width = " <<
|
||||
(int)capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_FRAME_WIDTH);
|
||||
cout << ", height = " <<
|
||||
(int)capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_FRAME_HEIGHT);
|
||||
cout << ", fps = " <<
|
||||
capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_FPS);
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void imshowImage(const char *winname, Mat &image, VideoCapture &capture)
|
||||
{
|
||||
if (g_showClosedPoint)
|
||||
{
|
||||
Mat uvMap;
|
||||
if (capture.retrieve(uvMap, CAP_INTELPERC_UVDEPTH_MAP))
|
||||
{
|
||||
float *uvmap = (float *)uvMap.ptr() + 2 * (g_closedDepthPoint[0] * uvMap.cols + g_closedDepthPoint[1]);
|
||||
int x = (int)((*uvmap) * image.cols); uvmap++;
|
||||
int y = (int)((*uvmap) * image.rows);
|
||||
|
||||
if ((0 <= x) && (0 <= y))
|
||||
{
|
||||
static const int pointSize = 4;
|
||||
for (int row = y; row < min(y + pointSize, image.rows); row++)
|
||||
{
|
||||
uchar* ptrDst = image.ptr(row) + x * 3 + 2;//+2 -> Red
|
||||
for (int col = 0; col < min(pointSize, image.cols - x); col++, ptrDst+=3)
|
||||
{
|
||||
*ptrDst = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
imshow(winname, image);
|
||||
}
|
||||
static void imshowIR(const char *winname, Mat &ir)
|
||||
{
|
||||
Mat image;
|
||||
if (g_showClosedPoint)
|
||||
{
|
||||
image.create(ir.rows, ir.cols, CV_8UC3);
|
||||
for (int row = 0; row < ir.rows; row++)
|
||||
{
|
||||
uchar* ptrDst = image.ptr(row);
|
||||
short* ptrSrc = (short*)ir.ptr(row);
|
||||
for (int col = 0; col < ir.cols; col++, ptrSrc++)
|
||||
{
|
||||
uchar val = (uchar) ((*ptrSrc) >> 2);
|
||||
*ptrDst = val; ptrDst++;
|
||||
*ptrDst = val; ptrDst++;
|
||||
*ptrDst = val; ptrDst++;
|
||||
}
|
||||
}
|
||||
|
||||
static const int pointSize = 4;
|
||||
for (int row = g_closedDepthPoint[0]; row < min(g_closedDepthPoint[0] + pointSize, image.rows); row++)
|
||||
{
|
||||
uchar* ptrDst = image.ptr(row) + g_closedDepthPoint[1] * 3 + 2;//+2 -> Red
|
||||
for (int col = 0; col < min(pointSize, image.cols - g_closedDepthPoint[1]); col++, ptrDst+=3)
|
||||
{
|
||||
*ptrDst = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
image.create(ir.rows, ir.cols, CV_8UC1);
|
||||
for (int row = 0; row < ir.rows; row++)
|
||||
{
|
||||
uchar* ptrDst = image.ptr(row);
|
||||
short* ptrSrc = (short*)ir.ptr(row);
|
||||
for (int col = 0; col < ir.cols; col++, ptrSrc++, ptrDst++)
|
||||
{
|
||||
*ptrDst = (uchar) ((*ptrSrc) >> 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imshow(winname, image);
|
||||
}
|
||||
static void imshowDepth(const char *winname, Mat &depth, VideoCapture &capture)
|
||||
{
|
||||
short lowValue = (short)capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE);
|
||||
short saturationValue = (short)capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE);
|
||||
|
||||
Mat image;
|
||||
if (g_showClosedPoint)
|
||||
{
|
||||
image.create(depth.rows, depth.cols, CV_8UC3);
|
||||
for (int row = 0; row < depth.rows; row++)
|
||||
{
|
||||
uchar* ptrDst = image.ptr(row);
|
||||
short* ptrSrc = (short*)depth.ptr(row);
|
||||
for (int col = 0; col < depth.cols; col++, ptrSrc++)
|
||||
{
|
||||
if ((lowValue == (*ptrSrc)) || (saturationValue == (*ptrSrc)))
|
||||
{
|
||||
*ptrDst = 0; ptrDst++;
|
||||
*ptrDst = 0; ptrDst++;
|
||||
*ptrDst = 0; ptrDst++;
|
||||
}
|
||||
else
|
||||
{
|
||||
uchar val = (uchar) ((*ptrSrc) >> 2);
|
||||
*ptrDst = val; ptrDst++;
|
||||
*ptrDst = val; ptrDst++;
|
||||
*ptrDst = val; ptrDst++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const int pointSize = 4;
|
||||
for (int row = g_closedDepthPoint[0]; row < min(g_closedDepthPoint[0] + pointSize, image.rows); row++)
|
||||
{
|
||||
uchar* ptrDst = image.ptr(row) + g_closedDepthPoint[1] * 3 + 2;//+2 -> Red
|
||||
for (int col = 0; col < min(pointSize, image.cols - g_closedDepthPoint[1]); col++, ptrDst+=3)
|
||||
{
|
||||
*ptrDst = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
image.create(depth.rows, depth.cols, CV_8UC1);
|
||||
for (int row = 0; row < depth.rows; row++)
|
||||
{
|
||||
uchar* ptrDst = image.ptr(row);
|
||||
short* ptrSrc = (short*)depth.ptr(row);
|
||||
for (int col = 0; col < depth.cols; col++, ptrSrc++, ptrDst++)
|
||||
{
|
||||
if ((lowValue == (*ptrSrc)) || (saturationValue == (*ptrSrc)))
|
||||
*ptrDst = 0;
|
||||
else
|
||||
*ptrDst = (uchar) ((*ptrSrc) >> 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
imshow(winname, image);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
parseCMDLine(argc, argv);
|
||||
|
||||
VideoCapture capture;
|
||||
capture.open(CAP_INTELPERC);
|
||||
if (!capture.isOpened())
|
||||
{
|
||||
cerr << "Can not open a capture object." << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_printStreamSetting)
|
||||
printStreamProperties(capture);
|
||||
|
||||
if (-1 != g_imageStreamProfileIdx)
|
||||
{
|
||||
if (!capture.set(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_INTELPERC_PROFILE_IDX, (double)g_imageStreamProfileIdx))
|
||||
{
|
||||
cerr << "Can not setup a image stream." << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (-1 != g_depthStreamProfileIdx)
|
||||
{
|
||||
if (!capture.set(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_PROFILE_IDX, (double)g_depthStreamProfileIdx))
|
||||
{
|
||||
cerr << "Can not setup a depth stream." << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (g_irStreamShow)
|
||||
{
|
||||
if (!capture.set(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_INTELPERC_PROFILE_IDX, 0.0))
|
||||
{
|
||||
cerr << "Can not setup a IR stream." << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Streams not selected" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Setup additional properties only after set profile of the stream
|
||||
if ( (-10000.0 < g_imageBrightness) && (g_imageBrightness < 10000.0))
|
||||
capture.set(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_BRIGHTNESS, g_imageBrightness);
|
||||
if ( (0 < g_imageContrast) && (g_imageContrast < 10000.0))
|
||||
capture.set(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_BRIGHTNESS, g_imageContrast);
|
||||
|
||||
int frame = 0;
|
||||
for(;;frame++)
|
||||
{
|
||||
Mat bgrImage;
|
||||
Mat depthImage;
|
||||
Mat irImage;
|
||||
|
||||
if (!capture.grab())
|
||||
{
|
||||
cout << "Can not grab images." << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((-1 != g_depthStreamProfileIdx) && (capture.retrieve(depthImage, CAP_INTELPERC_DEPTH_MAP)))
|
||||
{
|
||||
if (g_showClosedPoint)
|
||||
{
|
||||
double minVal = 0.0; double maxVal = 0.0;
|
||||
minMaxIdx(depthImage, &minVal, &maxVal, g_closedDepthPoint);
|
||||
}
|
||||
imshowDepth("depth image", depthImage, capture);
|
||||
}
|
||||
if ((g_irStreamShow) && (capture.retrieve(irImage, CAP_INTELPERC_IR_MAP)))
|
||||
imshowIR("ir image", irImage);
|
||||
if ((-1 != g_imageStreamProfileIdx) && (capture.retrieve(bgrImage, CAP_INTELPERC_IMAGE)))
|
||||
imshowImage("color image", bgrImage, capture);
|
||||
|
||||
if (g_printTiming)
|
||||
{
|
||||
cout << "Image frame: " << capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_POS_FRAMES)
|
||||
<< ", Depth(IR) frame: " << capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_POS_FRAMES) << endl;
|
||||
cout << "Image frame: " << capture.get(CAP_INTELPERC_IMAGE_GENERATOR | CAP_PROP_POS_MSEC)
|
||||
<< ", Depth(IR) frame: " << capture.get(CAP_INTELPERC_DEPTH_GENERATOR | CAP_PROP_POS_MSEC) << endl;
|
||||
}
|
||||
if( waitKey(30) >= 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
Mat frame;
|
||||
vector<Mat> audioData;
|
||||
VideoCapture cap;
|
||||
vector<int> params { CAP_PROP_AUDIO_STREAM, 0,
|
||||
CAP_PROP_VIDEO_STREAM, -1 };
|
||||
|
||||
cap.open(0, CAP_MSMF, params);
|
||||
if (!cap.isOpened())
|
||||
{
|
||||
cerr << "ERROR! Can't to open microphone" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int audioBaseIndex = (int)cap.get(CAP_PROP_AUDIO_BASE_INDEX);
|
||||
const int numberOfChannels = (int)cap.get(CAP_PROP_AUDIO_TOTAL_CHANNELS);
|
||||
cout << "CAP_PROP_AUDIO_DATA_DEPTH: " << depthToString((int)cap.get(CAP_PROP_AUDIO_DATA_DEPTH)) << endl;
|
||||
cout << "CAP_PROP_AUDIO_SAMPLES_PER_SECOND: " << cap.get(CAP_PROP_AUDIO_SAMPLES_PER_SECOND) << endl;
|
||||
cout << "CAP_PROP_AUDIO_TOTAL_CHANNELS: " << numberOfChannels << endl;
|
||||
cout << "CAP_PROP_AUDIO_TOTAL_STREAMS: " << cap.get(CAP_PROP_AUDIO_TOTAL_STREAMS) << endl;
|
||||
|
||||
const double cvTickFreq = getTickFrequency();
|
||||
int64 sysTimeCurr = getTickCount();
|
||||
int64 sysTimePrev = sysTimeCurr;
|
||||
while ((sysTimeCurr-sysTimePrev)/cvTickFreq < 10)
|
||||
{
|
||||
if (cap.grab())
|
||||
{
|
||||
for (int nCh = 0; nCh < numberOfChannels; nCh++)
|
||||
{
|
||||
cap.retrieve(frame, audioBaseIndex+nCh);
|
||||
audioData.push_back(frame);
|
||||
sysTimeCurr = getTickCount();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Grab error" << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int numberOfSamles = 0;
|
||||
for (auto item : audioData)
|
||||
numberOfSamles+=item.cols;
|
||||
cout << "Number of samples: " << numberOfSamles << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "opencv2/videoio.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
VideoCapture capture(CAP_INTELPERC);
|
||||
for(;;)
|
||||
{
|
||||
Mat depthMap;
|
||||
Mat image;
|
||||
Mat irImage;
|
||||
Mat adjMap;
|
||||
|
||||
capture.grab();
|
||||
capture.retrieve(depthMap,CAP_INTELPERC_DEPTH_MAP);
|
||||
capture.retrieve(image,CAP_INTELPERC_IMAGE);
|
||||
capture.retrieve(irImage,CAP_INTELPERC_IR_MAP);
|
||||
|
||||
normalize(depthMap, adjMap, 0, 255, NORM_MINMAX, CV_8UC1);
|
||||
applyColorMap(adjMap, adjMap, COLORMAP_JET);
|
||||
|
||||
imshow("RGB", image);
|
||||
imshow("IR", irImage);
|
||||
imshow("DEPTH", adjMap);
|
||||
if( waitKey( 30 ) >= 0 )
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ Check [a wiki](https://github.com/opencv/opencv/wiki/Deep-Learning-in-OpenCV) fo
|
||||
If OpenCV is built with [Intel's Inference Engine support](https://github.com/opencv/opencv/wiki/Intel%27s-Deep-Learning-Inference-Engine-backend) you can use [Intel's pre-trained](https://github.com/opencv/open_model_zoo) models.
|
||||
|
||||
There are different preprocessing parameters such mean subtraction or scale factors for different models.
|
||||
You may check the most popular models and their parameters at [models.yml](https://github.com/opencv/opencv/blob/master/samples/dnn/models.yml) configuration file. It might be also used for aliasing samples parameters. In example,
|
||||
You may check the most popular models and their parameters at [models.yml](https://github.com/opencv/opencv/blob/5.x/samples/dnn/models.yml) configuration file. It might be also used for aliasing samples parameters. In example,
|
||||
|
||||
```bash
|
||||
python object_detection.py opencv_fd --model /path/to/caffemodel --config /path/to/prototxt
|
||||
@@ -27,7 +27,7 @@ You can download sample models using ```download_models.py```. For example, the
|
||||
python download_models.py --save_dir FaceDetector opencv_fd
|
||||
```
|
||||
|
||||
You can use default configuration files adopted for OpenCV from [here](https://github.com/opencv/opencv_extra/tree/master/testdata/dnn).
|
||||
You can use default configuration files adopted for OpenCV from [here](https://github.com/opencv/opencv_extra/tree/5.x/testdata/dnn).
|
||||
|
||||
You also can use the script to download necessary files from your code. Assume you have the following code inside ```your_script.py```:
|
||||
|
||||
@@ -50,14 +50,14 @@ python your_script.py
|
||||
**Note** that you can provide a directory using **save_dir** parameter or via **OPENCV_SAVE_DIR** environment variable.
|
||||
|
||||
#### Face detection
|
||||
[An origin model](https://github.com/opencv/opencv/tree/master/samples/dnn/face_detector)
|
||||
[An origin model](https://github.com/opencv/opencv/tree/5.x/samples/dnn/face_detector)
|
||||
with single precision floating point weights has been quantized using [TensorFlow framework](https://www.tensorflow.org/).
|
||||
To achieve the best accuracy run the model on BGR images resized to `300x300` applying mean subtraction
|
||||
of values `(104, 177, 123)` for each blue, green and red channels correspondingly.
|
||||
|
||||
The following are accuracy metrics obtained using [COCO object detection evaluation
|
||||
tool](http://cocodataset.org/#detections-eval) on [FDDB dataset](http://vis-www.cs.umass.edu/fddb/)
|
||||
(see [script](https://github.com/opencv/opencv/blob/master/modules/dnn/misc/face_detector_accuracy.py))
|
||||
(see [script](https://github.com/opencv/opencv/blob/5.x/modules/dnn/misc/face_detector_accuracy.py))
|
||||
applying resize to `300x300` and keeping an origin images' sizes.
|
||||
```
|
||||
AP - Average Precision | FP32/FP16 | UINT8 | FP32/FP16 | UINT8 |
|
||||
@@ -79,6 +79,6 @@ AR @[ IoU=0.50:0.95 | area= large | maxDets=100 ] | 0.528 | 0.528 |
|
||||
|
||||
## References
|
||||
* [Models downloading script](https://github.com/opencv/opencv/samples/dnn/download_models.py)
|
||||
* [Configuration files adopted for OpenCV](https://github.com/opencv/opencv_extra/tree/master/testdata/dnn)
|
||||
* [Configuration files adopted for OpenCV](https://github.com/opencv/opencv_extra/tree/5.x/testdata/dnn)
|
||||
* [How to import models from TensorFlow Object Detection API](https://github.com/opencv/opencv/wiki/TensorFlow-Object-Detection-API)
|
||||
* [Names of classes from different datasets](https://github.com/opencv/opencv/tree/master/samples/data/dnn)
|
||||
* [Names of classes from different datasets](https://github.com/opencv/opencv/tree/5.x/samples/data/dnn)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
@@ -17,6 +18,7 @@ std::string keys =
|
||||
"{ std | 0.0 0.0 0.0 | Preprocess input image by dividing on a standard deviation.}"
|
||||
"{ crop | false | Preprocess input image by center cropping.}"
|
||||
"{ framework f | | Optional name of an origin framework of the model. Detect it automatically if it does not set. }"
|
||||
"{ needSoftmax | false | Use Softmax to post-process the output of the net.}"
|
||||
"{ classes | | Optional path to a text file with names of classes. }"
|
||||
"{ backend | 0 | Choose one of computation backends: "
|
||||
"0: automatically (by default), "
|
||||
@@ -24,7 +26,8 @@ std::string keys =
|
||||
"2: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), "
|
||||
"3: OpenCV implementation, "
|
||||
"4: VKCOM, "
|
||||
"5: CUDA },"
|
||||
"5: CUDA, "
|
||||
"6: WebNN }"
|
||||
"{ target | 0 | Choose one of target computation devices: "
|
||||
"0: CPU target (by default), "
|
||||
"1: OpenCL, "
|
||||
@@ -70,6 +73,9 @@ int main(int argc, char** argv)
|
||||
String framework = parser.get<String>("framework");
|
||||
int backendId = parser.get<int>("backend");
|
||||
int targetId = parser.get<int>("target");
|
||||
bool needSoftmax = parser.get<bool>("needSoftmax");
|
||||
std::cout<<"mean: "<<mean<<std::endl;
|
||||
std::cout<<"std: "<<std<<std::endl;
|
||||
|
||||
// Open file with classes names.
|
||||
if (parser.has("classes"))
|
||||
@@ -141,28 +147,62 @@ int main(int argc, char** argv)
|
||||
net.setInput(blob);
|
||||
//! [Set input blob]
|
||||
//! [Make forward pass]
|
||||
Mat prob = net.forward();
|
||||
//! [Make forward pass]
|
||||
|
||||
//! [Get a class with a highest score]
|
||||
Point classIdPoint;
|
||||
// double t_sum = 0.0;
|
||||
// double t;
|
||||
int classId;
|
||||
double confidence;
|
||||
minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
|
||||
int classId = classIdPoint.x;
|
||||
//! [Get a class with a highest score]
|
||||
cv::TickMeter timeRecorder;
|
||||
timeRecorder.reset();
|
||||
Mat prob = net.forward();
|
||||
double t1;
|
||||
timeRecorder.start();
|
||||
prob = net.forward();
|
||||
timeRecorder.stop();
|
||||
t1 = timeRecorder.getTimeMilli();
|
||||
|
||||
// Put efficiency information.
|
||||
std::vector<double> layersTimes;
|
||||
double freq = getTickFrequency() / 1000;
|
||||
double t = net.getPerfProfile(layersTimes) / freq;
|
||||
std::string label = format("Inference time: %.2f ms", t);
|
||||
timeRecorder.reset();
|
||||
for(int i = 0; i < 200; i++) {
|
||||
//! [Make forward pass]
|
||||
timeRecorder.start();
|
||||
prob = net.forward();
|
||||
timeRecorder.stop();
|
||||
|
||||
//! [Get a class with a highest score]
|
||||
Point classIdPoint;
|
||||
minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
|
||||
classId = classIdPoint.x;
|
||||
//! [Get a class with a highest score]
|
||||
|
||||
// Put efficiency information.
|
||||
// std::vector<double> layersTimes;
|
||||
// double freq = getTickFrequency() / 1000;
|
||||
// t = net.getPerfProfile(layersTimes) / freq;
|
||||
// t_sum += t;
|
||||
}
|
||||
if (needSoftmax == true)
|
||||
{
|
||||
float maxProb = 0.0;
|
||||
float sum = 0.0;
|
||||
Mat softmaxProb;
|
||||
|
||||
maxProb = *std::max_element(prob.begin<float>(), prob.end<float>());
|
||||
cv::exp(prob-maxProb, softmaxProb);
|
||||
sum = (float)cv::sum(softmaxProb)[0];
|
||||
softmaxProb /= sum;
|
||||
Point classIdPoint;
|
||||
minMaxLoc(softmaxProb.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
|
||||
classId = classIdPoint.x;
|
||||
}
|
||||
std::string label = format("Inference time of 1 round: %.2f ms", t1);
|
||||
std::string label2 = format("Average time of 200 rounds: %.2f ms", timeRecorder.getTimeMilli()/200);
|
||||
putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
|
||||
putText(frame, label2, Point(0, 35), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
|
||||
|
||||
// Print predicted class.
|
||||
label = format("%s: %.4f", (classes.empty() ? format("Class #%d", classId).c_str() :
|
||||
classes[classId].c_str()),
|
||||
confidence);
|
||||
putText(frame, label, Point(0, 40), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
|
||||
putText(frame, label, Point(0, 55), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
|
||||
|
||||
imshow(kWinName, frame);
|
||||
}
|
||||
|
||||
+201
-54
@@ -8,125 +8,272 @@
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
static Mat visualize(Mat input, Mat faces, int thickness=2)
|
||||
static
|
||||
void visualize(Mat& input, int frame, Mat& faces, double fps, int thickness = 2)
|
||||
{
|
||||
Mat output = input.clone();
|
||||
std::string fpsString = cv::format("FPS : %.2f", (float)fps);
|
||||
if (frame >= 0)
|
||||
cout << "Frame " << frame << ", ";
|
||||
cout << "FPS: " << fpsString << endl;
|
||||
for (int i = 0; i < faces.rows; i++)
|
||||
{
|
||||
// Print results
|
||||
cout << "Face " << i
|
||||
<< ", top-left coordinates: (" << faces.at<float>(i, 0) << ", " << faces.at<float>(i, 1) << "), "
|
||||
<< "box width: " << faces.at<float>(i, 2) << ", box height: " << faces.at<float>(i, 3) << ", "
|
||||
<< "score: " << faces.at<float>(i, 14) << "\n";
|
||||
<< "score: " << cv::format("%.2f", faces.at<float>(i, 14))
|
||||
<< endl;
|
||||
|
||||
// Draw bounding box
|
||||
rectangle(output, Rect2i(int(faces.at<float>(i, 0)), int(faces.at<float>(i, 1)), int(faces.at<float>(i, 2)), int(faces.at<float>(i, 3))), Scalar(0, 255, 0), thickness);
|
||||
rectangle(input, Rect2i(int(faces.at<float>(i, 0)), int(faces.at<float>(i, 1)), int(faces.at<float>(i, 2)), int(faces.at<float>(i, 3))), Scalar(0, 255, 0), thickness);
|
||||
// Draw landmarks
|
||||
circle(output, Point2i(int(faces.at<float>(i, 4)), int(faces.at<float>(i, 5))), 2, Scalar(255, 0, 0), thickness);
|
||||
circle(output, Point2i(int(faces.at<float>(i, 6)), int(faces.at<float>(i, 7))), 2, Scalar( 0, 0, 255), thickness);
|
||||
circle(output, Point2i(int(faces.at<float>(i, 8)), int(faces.at<float>(i, 9))), 2, Scalar( 0, 255, 0), thickness);
|
||||
circle(output, Point2i(int(faces.at<float>(i, 10)), int(faces.at<float>(i, 11))), 2, Scalar(255, 0, 255), thickness);
|
||||
circle(output, Point2i(int(faces.at<float>(i, 12)), int(faces.at<float>(i, 13))), 2, Scalar( 0, 255, 255), thickness);
|
||||
circle(input, Point2i(int(faces.at<float>(i, 4)), int(faces.at<float>(i, 5))), 2, Scalar(255, 0, 0), thickness);
|
||||
circle(input, Point2i(int(faces.at<float>(i, 6)), int(faces.at<float>(i, 7))), 2, Scalar(0, 0, 255), thickness);
|
||||
circle(input, Point2i(int(faces.at<float>(i, 8)), int(faces.at<float>(i, 9))), 2, Scalar(0, 255, 0), thickness);
|
||||
circle(input, Point2i(int(faces.at<float>(i, 10)), int(faces.at<float>(i, 11))), 2, Scalar(255, 0, 255), thickness);
|
||||
circle(input, Point2i(int(faces.at<float>(i, 12)), int(faces.at<float>(i, 13))), 2, Scalar(0, 255, 255), thickness);
|
||||
}
|
||||
return output;
|
||||
putText(input, fpsString, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 2);
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
CommandLineParser parser(argc, argv,
|
||||
"{help h | | Print this message.}"
|
||||
"{input i | | Path to the input image. Omit for detecting on default camera.}"
|
||||
"{model m | yunet.onnx | Path to the model. Download yunet.onnx in https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx.}"
|
||||
"{score_threshold | 0.9 | Filter out faces of score < score_threshold.}"
|
||||
"{nms_threshold | 0.3 | Suppress bounding boxes of iou >= nms_threshold.}"
|
||||
"{top_k | 5000 | Keep top_k bounding boxes before NMS.}"
|
||||
"{save s | false | Set true to save results. This flag is invalid when using camera.}"
|
||||
"{vis v | true | Set true to open a window for result visualization. This flag is invalid when using camera.}"
|
||||
"{help h | | Print this message}"
|
||||
"{image1 i1 | | Path to the input image1. Omit for detecting through VideoCapture}"
|
||||
"{image2 i2 | | Path to the input image2. When image1 and image2 parameters given then the program try to find a face on both images and runs face recognition algorithm}"
|
||||
"{video v | 0 | Path to the input video}"
|
||||
"{scale sc | 1.0 | Scale factor used to resize input video frames}"
|
||||
"{fd_model fd | yunet.onnx | Path to the model. Download yunet.onnx in https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx }"
|
||||
"{fr_model fr | face_recognizer_fast.onnx | Path to the face recognition model. Download the model at https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view}"
|
||||
"{score_threshold | 0.9 | Filter out faces of score < score_threshold}"
|
||||
"{nms_threshold | 0.3 | Suppress bounding boxes of iou >= nms_threshold}"
|
||||
"{top_k | 5000 | Keep top_k bounding boxes before NMS}"
|
||||
"{save s | false | Set true to save results. This flag is invalid when using camera}"
|
||||
);
|
||||
if (argc == 1 || parser.has("help"))
|
||||
if (parser.has("help"))
|
||||
{
|
||||
parser.printMessage();
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
String modelPath = parser.get<String>("model");
|
||||
String fd_modelPath = parser.get<String>("fd_model");
|
||||
String fr_modelPath = parser.get<String>("fr_model");
|
||||
|
||||
float scoreThreshold = parser.get<float>("score_threshold");
|
||||
float nmsThreshold = parser.get<float>("nms_threshold");
|
||||
int topK = parser.get<int>("top_k");
|
||||
|
||||
bool save = parser.get<bool>("save");
|
||||
bool vis = parser.get<bool>("vis");
|
||||
|
||||
double cosine_similar_thresh = 0.363;
|
||||
double l2norm_similar_thresh = 1.128;
|
||||
|
||||
//! [initialize_FaceDetectorYN]
|
||||
// Initialize FaceDetectorYN
|
||||
Ptr<FaceDetectorYN> detector = FaceDetectorYN::create(modelPath, "", Size(320, 320), scoreThreshold, nmsThreshold, topK);
|
||||
Ptr<FaceDetectorYN> detector = FaceDetectorYN::create(fd_modelPath, "", Size(320, 320), scoreThreshold, nmsThreshold, topK);
|
||||
//! [initialize_FaceDetectorYN]
|
||||
|
||||
TickMeter tm;
|
||||
|
||||
// If input is an image
|
||||
if (parser.has("input"))
|
||||
if (parser.has("image1"))
|
||||
{
|
||||
String input = parser.get<String>("input");
|
||||
Mat image = imread(input);
|
||||
String input1 = parser.get<String>("image1");
|
||||
Mat image1 = imread(samples::findFile(input1));
|
||||
if (image1.empty())
|
||||
{
|
||||
std::cerr << "Cannot read image: " << input1 << std::endl;
|
||||
return 2;
|
||||
}
|
||||
|
||||
tm.start();
|
||||
|
||||
//! [inference]
|
||||
// Set input size before inference
|
||||
detector->setInputSize(image.size());
|
||||
detector->setInputSize(image1.size());
|
||||
|
||||
// Inference
|
||||
Mat faces;
|
||||
detector->detect(image, faces);
|
||||
Mat faces1;
|
||||
detector->detect(image1, faces1);
|
||||
if (faces1.rows < 1)
|
||||
{
|
||||
std::cerr << "Cannot find a face in " << input1 << std::endl;
|
||||
return 1;
|
||||
}
|
||||
//! [inference]
|
||||
|
||||
tm.stop();
|
||||
// Draw results on the input image
|
||||
Mat result = visualize(image, faces);
|
||||
visualize(image1, -1, faces1, tm.getFPS());
|
||||
|
||||
// Save results if save is true
|
||||
if(save)
|
||||
if (save)
|
||||
{
|
||||
cout << "Results saved to result.jpg\n";
|
||||
imwrite("result.jpg", result);
|
||||
cout << "Saving result.jpg...\n";
|
||||
imwrite("result.jpg", image1);
|
||||
}
|
||||
|
||||
// Visualize results
|
||||
if (vis)
|
||||
imshow("image1", image1);
|
||||
pollKey(); // handle UI events to show content
|
||||
|
||||
if (parser.has("image2"))
|
||||
{
|
||||
namedWindow(input, WINDOW_AUTOSIZE);
|
||||
imshow(input, result);
|
||||
waitKey(0);
|
||||
String input2 = parser.get<String>("image2");
|
||||
Mat image2 = imread(samples::findFile(input2));
|
||||
if (image2.empty())
|
||||
{
|
||||
std::cerr << "Cannot read image2: " << input2 << std::endl;
|
||||
return 2;
|
||||
}
|
||||
|
||||
tm.reset();
|
||||
tm.start();
|
||||
detector->setInputSize(image2.size());
|
||||
|
||||
Mat faces2;
|
||||
detector->detect(image2, faces2);
|
||||
if (faces2.rows < 1)
|
||||
{
|
||||
std::cerr << "Cannot find a face in " << input2 << std::endl;
|
||||
return 1;
|
||||
}
|
||||
tm.stop();
|
||||
visualize(image2, -1, faces2, tm.getFPS());
|
||||
if (save)
|
||||
{
|
||||
cout << "Saving result2.jpg...\n";
|
||||
imwrite("result2.jpg", image2);
|
||||
}
|
||||
imshow("image2", image2);
|
||||
pollKey();
|
||||
|
||||
//! [initialize_FaceRecognizerSF]
|
||||
// Initialize FaceRecognizerSF
|
||||
Ptr<FaceRecognizerSF> faceRecognizer = FaceRecognizerSF::create(fr_modelPath, "");
|
||||
//! [initialize_FaceRecognizerSF]
|
||||
|
||||
|
||||
//! [facerecognizer]
|
||||
// Aligning and cropping facial image through the first face of faces detected.
|
||||
Mat aligned_face1, aligned_face2;
|
||||
faceRecognizer->alignCrop(image1, faces1.row(0), aligned_face1);
|
||||
faceRecognizer->alignCrop(image2, faces2.row(0), aligned_face2);
|
||||
|
||||
// Run feature extraction with given aligned_face
|
||||
Mat feature1, feature2;
|
||||
faceRecognizer->feature(aligned_face1, feature1);
|
||||
feature1 = feature1.clone();
|
||||
faceRecognizer->feature(aligned_face2, feature2);
|
||||
feature2 = feature2.clone();
|
||||
//! [facerecognizer]
|
||||
|
||||
//! [match]
|
||||
double cos_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_COSINE);
|
||||
double L2_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_NORM_L2);
|
||||
//! [match]
|
||||
|
||||
if (cos_score >= cosine_similar_thresh)
|
||||
{
|
||||
std::cout << "They have the same identity;";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "They have different identities;";
|
||||
}
|
||||
std::cout << " Cosine Similarity: " << cos_score << ", threshold: " << cosine_similar_thresh << ". (higher value means higher similarity, max 1.0)\n";
|
||||
|
||||
if (L2_score <= l2norm_similar_thresh)
|
||||
{
|
||||
std::cout << "They have the same identity;";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "They have different identities.";
|
||||
}
|
||||
std::cout << " NormL2 Distance: " << L2_score << ", threshold: " << l2norm_similar_thresh << ". (lower value means higher similarity, min 0.0)\n";
|
||||
}
|
||||
cout << "Press any key to exit..." << endl;
|
||||
waitKey(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int deviceId = 0;
|
||||
VideoCapture cap;
|
||||
cap.open(deviceId, CAP_ANY);
|
||||
int frameWidth = int(cap.get(CAP_PROP_FRAME_WIDTH));
|
||||
int frameHeight = int(cap.get(CAP_PROP_FRAME_HEIGHT));
|
||||
int frameWidth, frameHeight;
|
||||
float scale = parser.get<float>("scale");
|
||||
VideoCapture capture;
|
||||
std::string video = parser.get<string>("video");
|
||||
if (video.size() == 1 && isdigit(video[0]))
|
||||
capture.open(parser.get<int>("video"));
|
||||
else
|
||||
capture.open(samples::findFileOrKeep(video)); // keep GStreamer pipelines
|
||||
if (capture.isOpened())
|
||||
{
|
||||
frameWidth = int(capture.get(CAP_PROP_FRAME_WIDTH) * scale);
|
||||
frameHeight = int(capture.get(CAP_PROP_FRAME_HEIGHT) * scale);
|
||||
cout << "Video " << video
|
||||
<< ": width=" << frameWidth
|
||||
<< ", height=" << frameHeight
|
||||
<< endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Could not initialize video capturing: " << video << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
detector->setInputSize(Size(frameWidth, frameHeight));
|
||||
|
||||
Mat frame;
|
||||
TickMeter tm;
|
||||
String msg = "FPS: ";
|
||||
while(waitKey(1) < 0) // Press any key to exit
|
||||
cout << "Press 'SPACE' to save frame, any other key to exit..." << endl;
|
||||
int nFrame = 0;
|
||||
for (;;)
|
||||
{
|
||||
// Get frame
|
||||
if (!cap.read(frame))
|
||||
Mat frame;
|
||||
if (!capture.read(frame))
|
||||
{
|
||||
cerr << "No frames grabbed!\n";
|
||||
cerr << "Can't grab frame! Stop\n";
|
||||
break;
|
||||
}
|
||||
|
||||
resize(frame, frame, Size(frameWidth, frameHeight));
|
||||
|
||||
// Inference
|
||||
Mat faces;
|
||||
tm.start();
|
||||
detector->detect(frame, faces);
|
||||
tm.stop();
|
||||
|
||||
Mat result = frame.clone();
|
||||
// Draw results on the input image
|
||||
Mat result = visualize(frame, faces);
|
||||
putText(result, msg + to_string(tm.getFPS()), Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
|
||||
visualize(result, nFrame, faces, tm.getFPS());
|
||||
|
||||
// Visualize results
|
||||
imshow("Live", result);
|
||||
|
||||
tm.reset();
|
||||
int key = waitKey(1);
|
||||
bool saveFrame = save;
|
||||
if (key == ' ')
|
||||
{
|
||||
saveFrame = true;
|
||||
key = 0; // handled
|
||||
}
|
||||
|
||||
if (saveFrame)
|
||||
{
|
||||
std::string frame_name = cv::format("frame_%05d.png", nFrame);
|
||||
std::string result_name = cv::format("result_%05d.jpg", nFrame);
|
||||
cout << "Saving '" << frame_name << "' and '" << result_name << "' ...\n";
|
||||
imwrite(frame_name, frame);
|
||||
imwrite(result_name, result);
|
||||
}
|
||||
|
||||
++nFrame;
|
||||
|
||||
if (key > 0)
|
||||
break;
|
||||
}
|
||||
cout << "Processed " << nFrame << " frames" << endl;
|
||||
}
|
||||
}
|
||||
cout << "Done." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+90
-36
@@ -12,90 +12,144 @@ def str2bool(v):
|
||||
raise NotImplementedError
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--input', '-i', type=str, help='Path to the input image.')
|
||||
parser.add_argument('--model', '-m', type=str, default='yunet.onnx', help='Path to the model. Download the model at https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx.')
|
||||
parser.add_argument('--image1', '-i1', type=str, help='Path to the input image1. Omit for detecting on default camera.')
|
||||
parser.add_argument('--image2', '-i2', type=str, help='Path to the input image2. When image1 and image2 parameters given then the program try to find a face on both images and runs face recognition algorithm.')
|
||||
parser.add_argument('--video', '-v', type=str, help='Path to the input video.')
|
||||
parser.add_argument('--scale', '-sc', type=float, default=1.0, help='Scale factor used to resize input video frames.')
|
||||
parser.add_argument('--face_detection_model', '-fd', type=str, default='yunet.onnx', help='Path to the face detection model. Download the model at https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx.')
|
||||
parser.add_argument('--face_recognition_model', '-fr', type=str, default='face_recognizer_fast.onnx', help='Path to the face recognition model. Download the model at https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view.')
|
||||
parser.add_argument('--score_threshold', type=float, default=0.9, help='Filtering out faces of score < score_threshold.')
|
||||
parser.add_argument('--nms_threshold', type=float, default=0.3, help='Suppress bounding boxes of iou >= nms_threshold.')
|
||||
parser.add_argument('--top_k', type=int, default=5000, help='Keep top_k bounding boxes before NMS.')
|
||||
parser.add_argument('--save', '-s', type=str2bool, default=False, help='Set true to save results. This flag is invalid when using camera.')
|
||||
parser.add_argument('--vis', '-v', type=str2bool, default=True, help='Set true to open a window for result visualization. This flag is invalid when using camera.')
|
||||
args = parser.parse_args()
|
||||
|
||||
def visualize(input, faces, thickness=2):
|
||||
output = input.copy()
|
||||
def visualize(input, faces, fps, thickness=2):
|
||||
if faces[1] is not None:
|
||||
for idx, face in enumerate(faces[1]):
|
||||
print('Face {}, top-left coordinates: ({:.0f}, {:.0f}), box width: {:.0f}, box height {:.0f}, score: {:.2f}'.format(idx, face[0], face[1], face[2], face[3], face[-1]))
|
||||
|
||||
coords = face[:-1].astype(np.int32)
|
||||
cv.rectangle(output, (coords[0], coords[1]), (coords[0]+coords[2], coords[1]+coords[3]), (0, 255, 0), 2)
|
||||
cv.circle(output, (coords[4], coords[5]), 2, (255, 0, 0), 2)
|
||||
cv.circle(output, (coords[6], coords[7]), 2, (0, 0, 255), 2)
|
||||
cv.circle(output, (coords[8], coords[9]), 2, (0, 255, 0), 2)
|
||||
cv.circle(output, (coords[10], coords[11]), 2, (255, 0, 255), 2)
|
||||
cv.circle(output, (coords[12], coords[13]), 2, (0, 255, 255), 2)
|
||||
return output
|
||||
cv.rectangle(input, (coords[0], coords[1]), (coords[0]+coords[2], coords[1]+coords[3]), (0, 255, 0), thickness)
|
||||
cv.circle(input, (coords[4], coords[5]), 2, (255, 0, 0), thickness)
|
||||
cv.circle(input, (coords[6], coords[7]), 2, (0, 0, 255), thickness)
|
||||
cv.circle(input, (coords[8], coords[9]), 2, (0, 255, 0), thickness)
|
||||
cv.circle(input, (coords[10], coords[11]), 2, (255, 0, 255), thickness)
|
||||
cv.circle(input, (coords[12], coords[13]), 2, (0, 255, 255), thickness)
|
||||
cv.putText(input, 'FPS: {:.2f}'.format(fps), (1, 16), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
# Instantiate FaceDetectorYN
|
||||
## [initialize_FaceDetectorYN]
|
||||
detector = cv.FaceDetectorYN.create(
|
||||
args.model,
|
||||
args.face_detection_model,
|
||||
"",
|
||||
(320, 320),
|
||||
args.score_threshold,
|
||||
args.nms_threshold,
|
||||
args.top_k
|
||||
)
|
||||
## [initialize_FaceDetectorYN]
|
||||
|
||||
tm = cv.TickMeter()
|
||||
|
||||
# If input is an image
|
||||
if args.input is not None:
|
||||
image = cv.imread(args.input)
|
||||
if args.image1 is not None:
|
||||
img1 = cv.imread(cv.samples.findFile(args.image1))
|
||||
|
||||
tm.start()
|
||||
## [inference]
|
||||
# Set input size before inference
|
||||
detector.setInputSize((image.shape[1], image.shape[0]))
|
||||
detector.setInputSize((img1.shape[1], img1.shape[0]))
|
||||
|
||||
# Inference
|
||||
faces = detector.detect(image)
|
||||
faces1 = detector.detect(img1)
|
||||
## [inference]
|
||||
|
||||
tm.stop()
|
||||
assert faces1[1] is not None, 'Cannot find a face in {}'.format(args.image1)
|
||||
|
||||
# Draw results on the input image
|
||||
result = visualize(image, faces)
|
||||
visualize(img1, faces1, tm.getFPS())
|
||||
|
||||
# Save results if save is true
|
||||
if args.save:
|
||||
print('Resutls saved to result.jpg\n')
|
||||
cv.imwrite('result.jpg', result)
|
||||
print('Results saved to result.jpg\n')
|
||||
cv.imwrite('result.jpg', img1)
|
||||
|
||||
# Visualize results in a new window
|
||||
if args.vis:
|
||||
cv.namedWindow(args.input, cv.WINDOW_AUTOSIZE)
|
||||
cv.imshow(args.input, result)
|
||||
cv.waitKey(0)
|
||||
cv.imshow("image1", img1)
|
||||
|
||||
if args.image2 is not None:
|
||||
img2 = cv.imread(cv.samples.findFile(args.image2))
|
||||
|
||||
tm.reset()
|
||||
tm.start()
|
||||
detector.setInputSize((img2.shape[1], img2.shape[0]))
|
||||
faces2 = detector.detect(img2)
|
||||
tm.stop()
|
||||
assert faces2[1] is not None, 'Cannot find a face in {}'.format(args.image2)
|
||||
visualize(img2, faces2, tm.getFPS())
|
||||
cv.imshow("image2", img2)
|
||||
|
||||
## [initialize_FaceRecognizerSF]
|
||||
recognizer = cv.FaceRecognizerSF.create(
|
||||
args.face_recognition_model,"")
|
||||
## [initialize_FaceRecognizerSF]
|
||||
|
||||
## [facerecognizer]
|
||||
# Align faces
|
||||
face1_align = recognizer.alignCrop(img1, faces1[1][0])
|
||||
face2_align = recognizer.alignCrop(img2, faces2[1][0])
|
||||
|
||||
# Extract features
|
||||
face1_feature = recognizer.feature(face1_align)
|
||||
face2_feature = recognizer.feature(face2_align)
|
||||
## [facerecognizer]
|
||||
|
||||
cosine_similarity_threshold = 0.363
|
||||
l2_similarity_threshold = 1.128
|
||||
|
||||
## [match]
|
||||
cosine_score = recognizer.match(face1_feature, face2_feature, cv.FaceRecognizerSF_FR_COSINE)
|
||||
l2_score = recognizer.match(face1_feature, face2_feature, cv.FaceRecognizerSF_FR_NORM_L2)
|
||||
## [match]
|
||||
|
||||
msg = 'different identities'
|
||||
if cosine_score >= cosine_similarity_threshold:
|
||||
msg = 'the same identity'
|
||||
print('They have {}. Cosine Similarity: {}, threshold: {} (higher value means higher similarity, max 1.0).'.format(msg, cosine_score, cosine_similarity_threshold))
|
||||
|
||||
msg = 'different identities'
|
||||
if l2_score <= l2_similarity_threshold:
|
||||
msg = 'the same identity'
|
||||
print('They have {}. NormL2 Distance: {}, threshold: {} (lower value means higher similarity, min 0.0).'.format(msg, l2_score, l2_similarity_threshold))
|
||||
cv.waitKey(0)
|
||||
else: # Omit input to call default camera
|
||||
deviceId = 0
|
||||
if args.video is not None:
|
||||
deviceId = args.video
|
||||
else:
|
||||
deviceId = 0
|
||||
cap = cv.VideoCapture(deviceId)
|
||||
frameWidth = int(cap.get(cv.CAP_PROP_FRAME_WIDTH))
|
||||
frameHeight = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))
|
||||
frameWidth = int(cap.get(cv.CAP_PROP_FRAME_WIDTH)*args.scale)
|
||||
frameHeight = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)*args.scale)
|
||||
detector.setInputSize([frameWidth, frameHeight])
|
||||
|
||||
tm = cv.TickMeter()
|
||||
while cv.waitKey(1) < 0:
|
||||
hasFrame, frame = cap.read()
|
||||
if not hasFrame:
|
||||
print('No frames grabbed!')
|
||||
break
|
||||
|
||||
frame = cv.resize(frame, (frameWidth, frameHeight))
|
||||
|
||||
# Inference
|
||||
tm.start()
|
||||
faces = detector.detect(frame) # faces is a tuple
|
||||
tm.stop()
|
||||
|
||||
# Draw results on the input image
|
||||
frame = visualize(frame, faces)
|
||||
visualize(frame, faces, tm.getFPS())
|
||||
|
||||
cv.putText(frame, 'FPS: {}'.format(tm.getFPS()), (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0))
|
||||
|
||||
# Visualize results in a new Window
|
||||
# Visualize results
|
||||
cv.imshow('Live', frame)
|
||||
|
||||
tm.reset()
|
||||
cv.destroyAllWindows()
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "opencv2/dnn.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "opencv2/objdetect.hpp"
|
||||
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
if (argc != 5)
|
||||
{
|
||||
std::cerr << "Usage " << argv[0] << ": "
|
||||
<< "<det_onnx_path> "
|
||||
<< "<reg_onnx_path> "
|
||||
<< "<image1>"
|
||||
<< "<image2>\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
String det_onnx_path = argv[1];
|
||||
String reg_onnx_path = argv[2];
|
||||
String image1_path = argv[3];
|
||||
String image2_path = argv[4];
|
||||
std::cout<<image1_path<<" "<<image2_path<<std::endl;
|
||||
Mat image1 = imread(image1_path);
|
||||
Mat image2 = imread(image2_path);
|
||||
|
||||
float score_thresh = 0.9f;
|
||||
float nms_thresh = 0.3f;
|
||||
double cosine_similar_thresh = 0.363;
|
||||
double l2norm_similar_thresh = 1.128;
|
||||
int top_k = 5000;
|
||||
|
||||
// Initialize FaceDetector
|
||||
Ptr<FaceDetectorYN> faceDetector;
|
||||
|
||||
faceDetector = FaceDetectorYN::create(det_onnx_path, "", image1.size(), score_thresh, nms_thresh, top_k);
|
||||
Mat faces_1;
|
||||
faceDetector->detect(image1, faces_1);
|
||||
if (faces_1.rows < 1)
|
||||
{
|
||||
std::cerr << "Cannot find a face in " << image1_path << "\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
faceDetector = FaceDetectorYN::create(det_onnx_path, "", image2.size(), score_thresh, nms_thresh, top_k);
|
||||
Mat faces_2;
|
||||
faceDetector->detect(image2, faces_2);
|
||||
if (faces_2.rows < 1)
|
||||
{
|
||||
std::cerr << "Cannot find a face in " << image2_path << "\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Initialize FaceRecognizerSF
|
||||
Ptr<FaceRecognizerSF> faceRecognizer = FaceRecognizerSF::create(reg_onnx_path, "");
|
||||
|
||||
|
||||
Mat aligned_face1, aligned_face2;
|
||||
faceRecognizer->alignCrop(image1, faces_1.row(0), aligned_face1);
|
||||
faceRecognizer->alignCrop(image2, faces_2.row(0), aligned_face2);
|
||||
|
||||
Mat feature1, feature2;
|
||||
faceRecognizer->feature(aligned_face1, feature1);
|
||||
feature1 = feature1.clone();
|
||||
faceRecognizer->feature(aligned_face2, feature2);
|
||||
feature2 = feature2.clone();
|
||||
|
||||
double cos_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_COSINE);
|
||||
double L2_score = faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_NORM_L2);
|
||||
|
||||
if(cos_score >= cosine_similar_thresh)
|
||||
{
|
||||
std::cout << "They have the same identity;";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "They have different identities;";
|
||||
}
|
||||
std::cout << " Cosine Similarity: " << cos_score << ", threshold: " << cosine_similar_thresh << ". (higher value means higher similarity, max 1.0)\n";
|
||||
|
||||
if(L2_score <= l2norm_similar_thresh)
|
||||
{
|
||||
std::cout << "They have the same identity;";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "They have different identities.";
|
||||
}
|
||||
std::cout << " NormL2 Distance: " << L2_score << ", threshold: " << l2norm_similar_thresh << ". (lower value means higher similarity, min 0.0)\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import argparse
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--input1', '-i1', type=str, help='Path to the input image1.')
|
||||
parser.add_argument('--input2', '-i2', type=str, help='Path to the input image2.')
|
||||
parser.add_argument('--face_detection_model', '-fd', type=str, help='Path to the face detection model. Download the model at https://github.com/ShiqiYu/libfacedetection.train/tree/master/tasks/task1/onnx.')
|
||||
parser.add_argument('--face_recognition_model', '-fr', type=str, help='Path to the face recognition model. Download the model at https://drive.google.com/file/d/1ClK9WiB492c5OZFKveF3XiHCejoOxINW/view.')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Read the input image
|
||||
img1 = cv.imread(args.input1)
|
||||
img2 = cv.imread(args.input2)
|
||||
|
||||
# Instantiate face detector and recognizer
|
||||
detector = cv.FaceDetectorYN.create(
|
||||
args.face_detection_model,
|
||||
"",
|
||||
(img1.shape[1], img1.shape[0])
|
||||
)
|
||||
recognizer = cv.FaceRecognizerSF.create(
|
||||
args.face_recognition_model,
|
||||
""
|
||||
)
|
||||
|
||||
# Detect face
|
||||
detector.setInputSize((img1.shape[1], img1.shape[0]))
|
||||
face1 = detector.detect(img1)
|
||||
detector.setInputSize((img2.shape[1], img2.shape[0]))
|
||||
face2 = detector.detect(img2)
|
||||
assert face1[1].shape[0] > 0, 'Cannot find a face in {}'.format(args.input1)
|
||||
assert face2[1].shape[0] > 0, 'Cannot find a face in {}'.format(args.input2)
|
||||
|
||||
# Align faces
|
||||
face1_align = recognizer.alignCrop(img1, face1[1][0])
|
||||
face2_align = recognizer.alignCrop(img2, face2[1][0])
|
||||
|
||||
# Extract features
|
||||
face1_feature = recognizer.faceFeature(face1_align)
|
||||
face2_feature = recognizer.faceFeature(face2_align)
|
||||
|
||||
# Calculate distance (0: cosine, 1: L2)
|
||||
cosine_similarity_threshold = 0.363
|
||||
cosine_score = recognizer.faceMatch(face1_feature, face2_feature, 0)
|
||||
msg = 'different identities'
|
||||
if cosine_score >= cosine_similarity_threshold:
|
||||
msg = 'the same identity'
|
||||
print('They have {}. Cosine Similarity: {}, threshold: {} (higher value means higher similarity, max 1.0).'.format(msg, cosine_score, cosine_similarity_threshold))
|
||||
|
||||
l2_similarity_threshold = 1.128
|
||||
l2_score = recognizer.faceMatch(face1_feature, face2_feature, 1)
|
||||
msg = 'different identities'
|
||||
if l2_score <= l2_similarity_threshold:
|
||||
msg = 'the same identity'
|
||||
print('They have {}. NormL2 Distance: {}, threshold: {} (lower value means higher similarity, min 0.0).'.format(msg, l2_score, l2_similarity_threshold))
|
||||
@@ -69,7 +69,7 @@ function recognize(face) {
|
||||
|
||||
function loadModels(callback) {
|
||||
var utils = new Utils('');
|
||||
var proto = 'https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy_lowres.prototxt';
|
||||
var proto = 'https://raw.githubusercontent.com/opencv/opencv/5.x/samples/dnn/face_detector/deploy_lowres.prototxt';
|
||||
var weights = 'https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180205_fp16/res10_300x300_ssd_iter_140000_fp16.caffemodel';
|
||||
var recognModel = 'https://raw.githubusercontent.com/pyannote/pyannote-data/master/openface.nn4.small2.v1.t7';
|
||||
utils.createFileFromUrl('face_detector.prototxt', proto, () => {
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
|
||||
#ifdef CV_CXX11
|
||||
#if defined(CV_CXX11) && defined(HAVE_THREADS)
|
||||
#define USE_THREADS 1
|
||||
#endif
|
||||
|
||||
#ifdef USE_THREADS
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
@@ -56,7 +60,7 @@ void drawPred(int classId, float conf, int left, int top, int right, int bottom,
|
||||
|
||||
void callback(int pos, void* userdata);
|
||||
|
||||
#ifdef CV_CXX11
|
||||
#ifdef USE_THREADS
|
||||
template <typename T>
|
||||
class QueueFPS : public std::queue<T>
|
||||
{
|
||||
@@ -106,7 +110,7 @@ private:
|
||||
TickMeter tm;
|
||||
std::mutex mutex;
|
||||
};
|
||||
#endif // CV_CXX11
|
||||
#endif // USE_THREADS
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
@@ -171,7 +175,7 @@ int main(int argc, char** argv)
|
||||
else
|
||||
cap.open(parser.get<int>("device"));
|
||||
|
||||
#ifdef CV_CXX11
|
||||
#ifdef USE_THREADS
|
||||
bool process = true;
|
||||
|
||||
// Frames capturing thread
|
||||
@@ -271,7 +275,7 @@ int main(int argc, char** argv)
|
||||
framesThread.join();
|
||||
processingThread.join();
|
||||
|
||||
#else // CV_CXX11
|
||||
#else // USE_THREADS
|
||||
if (asyncNumReq)
|
||||
CV_Error(Error::StsNotImplemented, "Asynchronous forward is supported only with Inference Engine backend.");
|
||||
|
||||
@@ -302,7 +306,7 @@ int main(int argc, char** argv)
|
||||
|
||||
imshow(kWinName, frame);
|
||||
}
|
||||
#endif // CV_CXX11
|
||||
#endif // USE_THREADS
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
//
|
||||
// it can be used for body pose detection, using either the COCO model(18 parts):
|
||||
// http://posefs1.perception.cs.cmu.edu/OpenPose/models/pose/coco/pose_iter_440000.caffemodel
|
||||
// https://raw.githubusercontent.com/opencv/opencv_extra/master/testdata/dnn/openpose_pose_coco.prototxt
|
||||
// https://raw.githubusercontent.com/opencv/opencv_extra/5.x/testdata/dnn/openpose_pose_coco.prototxt
|
||||
//
|
||||
// or the MPI model(16 parts):
|
||||
// http://posefs1.perception.cs.cmu.edu/OpenPose/models/pose/mpi/pose_iter_160000.caffemodel
|
||||
// https://raw.githubusercontent.com/opencv/opencv_extra/master/testdata/dnn/openpose_pose_mpi_faster_4_stages.prototxt
|
||||
// https://raw.githubusercontent.com/opencv/opencv_extra/5.x/testdata/dnn/openpose_pose_mpi_faster_4_stages.prototxt
|
||||
//
|
||||
// (to simplify this sample, the body models are restricted to a single person.)
|
||||
//
|
||||
|
||||
@@ -300,7 +300,7 @@ class SiamRPNTracker:
|
||||
# clip boundary
|
||||
cx, cy, width, height = self._bbox_clip(cx, cy, width, height, img.shape[:2])
|
||||
|
||||
# udpate state
|
||||
# update state
|
||||
self.center_pos = np.array([cx, cy])
|
||||
self.w = width
|
||||
self.h = height
|
||||
|
||||
@@ -2,7 +2,6 @@ import numpy as np
|
||||
import cv2 as cv
|
||||
import argparse
|
||||
import os
|
||||
import soundfile as sf # Temporary import to load audio files
|
||||
|
||||
'''
|
||||
You can download the converted onnx model from https://drive.google.com/drive/folders/1wLtxyao4ItAg8tt4Sb63zt6qXzhcQoR6?usp=sharing
|
||||
@@ -399,11 +398,6 @@ def predict(features, net, decoder):
|
||||
decoder : Decoder object
|
||||
return : Predicted text
|
||||
'''
|
||||
# This is a workaround https://github.com/opencv/opencv/issues/19091
|
||||
# expanding 1 dimentions allows us to pass it to the network
|
||||
# from python. This should be resolved in the future.
|
||||
features = np.expand_dims(features,axis=3)
|
||||
|
||||
# make prediction
|
||||
net.setInput(features)
|
||||
output = net.forward()
|
||||
@@ -412,6 +406,63 @@ def predict(features, net, decoder):
|
||||
prediction = decoder.decode(output.squeeze(0))
|
||||
return prediction[0]
|
||||
|
||||
def readAudioFile(file, audioStream):
|
||||
cap = cv.VideoCapture(file)
|
||||
samplingRate = 16000
|
||||
params = np.asarray([cv.CAP_PROP_AUDIO_STREAM, audioStream,
|
||||
cv.CAP_PROP_VIDEO_STREAM, -1,
|
||||
cv.CAP_PROP_AUDIO_DATA_DEPTH, cv.CV_32F,
|
||||
cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND, samplingRate
|
||||
])
|
||||
cap.open(file, cv.CAP_ANY, params)
|
||||
if cap.isOpened() is False:
|
||||
print("Error : Can't read audio file:", file, "with audioStream = ", audioStream)
|
||||
return
|
||||
audioBaseIndex = int (cap.get(cv.CAP_PROP_AUDIO_BASE_INDEX))
|
||||
inputAudio = []
|
||||
while(1):
|
||||
if (cap.grab()):
|
||||
frame = np.asarray([])
|
||||
frame = cap.retrieve(frame, audioBaseIndex)
|
||||
for i in range(len(frame[1][0])):
|
||||
inputAudio.append(frame[1][0][i])
|
||||
else:
|
||||
break
|
||||
inputAudio = np.asarray(inputAudio, dtype=np.float64)
|
||||
return inputAudio, samplingRate
|
||||
|
||||
def readAudioMicrophone(microTime):
|
||||
cap = cv.VideoCapture()
|
||||
samplingRate = 16000
|
||||
params = np.asarray([cv.CAP_PROP_AUDIO_STREAM, 0,
|
||||
cv.CAP_PROP_VIDEO_STREAM, -1,
|
||||
cv.CAP_PROP_AUDIO_DATA_DEPTH, cv.CV_32F,
|
||||
cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND, samplingRate
|
||||
])
|
||||
cap.open(0, cv.CAP_ANY, params)
|
||||
if cap.isOpened() is False:
|
||||
print("Error: Can't open microphone")
|
||||
print("Error: problems with audio reading, check input arguments")
|
||||
return
|
||||
audioBaseIndex = int(cap.get(cv.CAP_PROP_AUDIO_BASE_INDEX))
|
||||
cvTickFreq = cv.getTickFrequency()
|
||||
sysTimeCurr = cv.getTickCount()
|
||||
sysTimePrev = sysTimeCurr
|
||||
inputAudio = []
|
||||
while ((sysTimeCurr - sysTimePrev) / cvTickFreq < microTime):
|
||||
if (cap.grab()):
|
||||
frame = np.asarray([])
|
||||
frame = cap.retrieve(frame, audioBaseIndex)
|
||||
for i in range(len(frame[1][0])):
|
||||
inputAudio.append(frame[1][0][i])
|
||||
sysTimeCurr = cv.getTickCount()
|
||||
else:
|
||||
print("Error: Grab error")
|
||||
break
|
||||
inputAudio = np.asarray(inputAudio, dtype=np.float64)
|
||||
print("Number of samples: ", len(inputAudio))
|
||||
return inputAudio, samplingRate
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
# Computation backends supported by layers
|
||||
@@ -421,7 +472,10 @@ if __name__ == '__main__':
|
||||
|
||||
parser = argparse.ArgumentParser(description='This script runs Jasper Speech recognition model',
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('--input_audio', type=str, required=True, help='Path to input audio file. OR Path to a txt file with relative path to multiple audio files in different lines')
|
||||
parser.add_argument('--input_type', type=str, required=True, help='file or microphone')
|
||||
parser.add_argument('--micro_time', type=int, default=15, help='Duration of microphone work in seconds. Must be more than 6 sec')
|
||||
parser.add_argument('--input_audio', type=str, help='Path to input audio file. OR Path to a txt file with relative path to multiple audio files in different lines')
|
||||
parser.add_argument('--audio_stream', type=int, default=0, help='CAP_PROP_AUDIO_STREAM value')
|
||||
parser.add_argument('--show_spectrogram', action='store_true', help='Whether to show a spectrogram of the input audio.')
|
||||
parser.add_argument('--model', type=str, default='jasper.onnx', help='Path to the onnx file of Jasper. default="jasper.onnx"')
|
||||
parser.add_argument('--output', type=str, help='Path to file where recognized audio transcript must be saved. Leave this to print on console.')
|
||||
@@ -442,28 +496,35 @@ if __name__ == '__main__':
|
||||
raise OSError("Input audio file does not exist")
|
||||
if not os.path.isfile(args.model):
|
||||
raise OSError("Jasper model file does not exist")
|
||||
if args.input_audio.endswith('.txt'):
|
||||
with open(args.input_audio) as f:
|
||||
content = f.readlines()
|
||||
content = [x.strip() for x in content]
|
||||
audio_file_paths = content
|
||||
for audio_file_path in audio_file_paths:
|
||||
if not os.path.isfile(audio_file_path):
|
||||
raise OSError("Audio file({audio_file_path}) does not exist")
|
||||
else:
|
||||
audio_file_paths = [args.input_audio]
|
||||
audio_file_paths = [os.path.abspath(x) for x in audio_file_paths]
|
||||
|
||||
# Read audio Files
|
||||
features = []
|
||||
try:
|
||||
if args.input_type == "file":
|
||||
if args.input_audio.endswith('.txt'):
|
||||
with open(args.input_audio) as f:
|
||||
content = f.readlines()
|
||||
content = [x.strip() for x in content]
|
||||
audio_file_paths = content
|
||||
for audio_file_path in audio_file_paths:
|
||||
if not os.path.isfile(audio_file_path):
|
||||
raise OSError("Audio file({audio_file_path}) does not exist")
|
||||
else:
|
||||
audio_file_paths = [args.input_audio]
|
||||
audio_file_paths = [os.path.abspath(x) for x in audio_file_paths]
|
||||
|
||||
# Read audio Files
|
||||
for audio_file_path in audio_file_paths:
|
||||
audio = sf.read(audio_file_path)
|
||||
# If audio is stereo, just take one channel.
|
||||
X = audio[0] if audio[0].ndim==1 else audio[0][:,0]
|
||||
features.append(X)
|
||||
except:
|
||||
raise Exception(f"Soundfile cannot read {args.input_audio}. Try a different format")
|
||||
audio = readAudioFile(audio_file_path, args.audio_stream)
|
||||
if audio is None:
|
||||
raise Exception(f"Can't read {args.input_audio}. Try a different format")
|
||||
features.append(audio[0])
|
||||
elif args.input_type == "microphone":
|
||||
# Read audio from microphone
|
||||
audio = readAudioMicrophone(args.micro_time)
|
||||
if audio is None:
|
||||
raise Exception(f"Can't open microphone. Try a different format")
|
||||
features.append(audio[0])
|
||||
else:
|
||||
raise Exception(f"input_type {args.input_type} doesn't exist. Please enter 'file' or 'microphone'")
|
||||
|
||||
# Get Filterbank Features
|
||||
feature_extractor = FilterbankFeatures()
|
||||
|
||||
@@ -270,12 +270,12 @@ def createSSDGraph(modelPath, configPath, outputPath):
|
||||
addConstNode('concat/axis_flatten', [-1], graph_def)
|
||||
addConstNode('PriorBox/concat/axis', [-2], graph_def)
|
||||
|
||||
for label in ['ClassPredictor', 'BoxEncodingPredictor' if box_predictor is 'convolutional' else 'BoxPredictor']:
|
||||
for label in ['ClassPredictor', 'BoxEncodingPredictor' if box_predictor == 'convolutional' else 'BoxPredictor']:
|
||||
concatInputs = []
|
||||
for i in range(num_layers):
|
||||
# Flatten predictions
|
||||
flatten = NodeDef()
|
||||
if box_predictor is 'convolutional':
|
||||
if box_predictor == 'convolutional':
|
||||
inpName = 'BoxPredictor_%d/%s/BiasAdd' % (i, label)
|
||||
else:
|
||||
if i == 0:
|
||||
@@ -308,7 +308,7 @@ def createSSDGraph(modelPath, configPath, outputPath):
|
||||
priorBox = NodeDef()
|
||||
priorBox.name = 'PriorBox_%d' % i
|
||||
priorBox.op = 'PriorBox'
|
||||
if box_predictor is 'convolutional':
|
||||
if box_predictor == 'convolutional':
|
||||
priorBox.input.append('BoxPredictor_%d/BoxEncodingPredictor/BiasAdd' % i)
|
||||
else:
|
||||
if i == 0:
|
||||
|
||||
@@ -26,9 +26,9 @@ sudo apt install -y wget unzip
|
||||
# [wget]
|
||||
|
||||
# [download]
|
||||
wget -O opencv.zip https://github.com/opencv/opencv/archive/master.zip
|
||||
wget -O opencv.zip https://github.com/opencv/opencv/archive/5.x.zip
|
||||
unzip opencv.zip
|
||||
mv opencv-master opencv
|
||||
mv opencv-5.x opencv
|
||||
# [download]
|
||||
|
||||
# [prepare]
|
||||
|
||||
@@ -27,7 +27,7 @@ sudo apt install -y git
|
||||
|
||||
# [download]
|
||||
git clone https://github.com/opencv/opencv.git
|
||||
git -C opencv checkout master
|
||||
git -C opencv checkout 5.x
|
||||
# [download]
|
||||
|
||||
# [prepare]
|
||||
|
||||
@@ -12,14 +12,14 @@ fi
|
||||
sudo apt update && sudo apt install -y cmake g++ wget unzip
|
||||
|
||||
# Download and unpack sources
|
||||
wget -O opencv.zip https://github.com/opencv/opencv/archive/master.zip
|
||||
wget -O opencv.zip https://github.com/opencv/opencv/archive/5.x.zip
|
||||
unzip opencv.zip
|
||||
|
||||
# Create build directory
|
||||
mkdir -p build && cd build
|
||||
|
||||
# Configure
|
||||
cmake ../opencv-master
|
||||
cmake ../opencv-5.x
|
||||
|
||||
# Build
|
||||
cmake --build .
|
||||
|
||||
@@ -12,8 +12,8 @@ fi
|
||||
sudo apt update && sudo apt install -y cmake g++ wget unzip
|
||||
|
||||
# Download and unpack sources
|
||||
wget -O opencv.zip https://github.com/opencv/opencv/archive/master.zip
|
||||
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/master.zip
|
||||
wget -O opencv.zip https://github.com/opencv/opencv/archive/5.x.zip
|
||||
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/5.x.zip
|
||||
unzip opencv.zip
|
||||
unzip opencv_contrib.zip
|
||||
|
||||
@@ -21,7 +21,7 @@ unzip opencv_contrib.zip
|
||||
mkdir -p build && cd build
|
||||
|
||||
# Configure
|
||||
cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-master/modules ../opencv-master
|
||||
cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-5.x/modules ../opencv-5.x
|
||||
|
||||
# Build
|
||||
cmake --build .
|
||||
|
||||
@@ -23,7 +23,7 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
|
||||
endif()
|
||||
foreach(sample_filename ${all_samples})
|
||||
ocv_define_sample(tgt ${sample_filename} opengl)
|
||||
ocv_target_link_libraries(${tgt} PRIVATE ${OPENCV_LINKER_LIBS} ${OPENCV_OPENGL_SAMPLES_REQUIRED_DEPS})
|
||||
ocv_target_link_libraries(${tgt} PRIVATE "${OPENGL_LIBRARIES}" "${OPENCV_OPENGL_SAMPLES_REQUIRED_DEPS}")
|
||||
if(sample_filename STREQUAL "opengl_interop.cpp")
|
||||
ocv_target_link_libraries(${tgt} PRIVATE ${X11_LIBRARIES})
|
||||
ocv_target_include_directories(${tgt} ${X11_INCLUDE_DIR})
|
||||
|
||||
@@ -0,0 +1,804 @@
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import math
|
||||
import argparse
|
||||
|
||||
class AudioDrawing:
|
||||
'''
|
||||
Used for drawing audio graphics
|
||||
'''
|
||||
def __init__(self, args):
|
||||
|
||||
self.inputType = args.inputType
|
||||
self.draw = args.draw
|
||||
self.graph = args.graph
|
||||
self.audio = cv.samples.findFile(args.audio)
|
||||
self.audioStream = args.audioStream
|
||||
|
||||
self.windowType = args.windowType
|
||||
self.windLen = args.windLen
|
||||
self.overlap = args.overlap
|
||||
|
||||
self.enableGrid = args.enableGrid
|
||||
|
||||
self.rows = args.rows
|
||||
self.cols = args.cols
|
||||
|
||||
self.xmarkup = args.xmarkup
|
||||
self.ymarkup = args.ymarkup
|
||||
self.zmarkup = args.zmarkup
|
||||
|
||||
self.microTime = args.microTime
|
||||
self.frameSizeTime = args.frameSizeTime
|
||||
self.updateTime = args.updateTime
|
||||
self.waitTime = args.waitTime
|
||||
|
||||
if self.initAndCheckArgs(args) is False:
|
||||
exit()
|
||||
|
||||
|
||||
def Draw(self):
|
||||
if self.draw == "static":
|
||||
|
||||
if self.inputType == "file":
|
||||
samplingRate, inputAudio = self.readAudioFile(self.audio)
|
||||
|
||||
elif self.inputType == "microphone":
|
||||
samplingRate, inputAudio = self.readAudioMicrophone()
|
||||
|
||||
duration = len(inputAudio) // samplingRate
|
||||
|
||||
# since the dimensional grid is counted in integer seconds,
|
||||
# if the input audio has an incomplete last second,
|
||||
# then it is filled with zeros to complete
|
||||
remainder = len(inputAudio) % samplingRate
|
||||
if remainder != 0:
|
||||
sizeToFullSec = samplingRate - remainder
|
||||
zeroArr = np.zeros(sizeToFullSec)
|
||||
inputAudio = np.concatenate((inputAudio, zeroArr), axis=0)
|
||||
duration += 1
|
||||
print("Update duration of audio to full second with ",
|
||||
sizeToFullSec, " zero samples")
|
||||
print("New number of samples ", len(inputAudio))
|
||||
|
||||
if duration <= self.xmarkup:
|
||||
self.xmarkup = duration + 1
|
||||
|
||||
if self.graph == "ampl":
|
||||
imgAmplitude = self.drawAmplitude(inputAudio)
|
||||
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, inputAudio, samplingRate)
|
||||
cv.imshow("Display window", imgAmplitude)
|
||||
cv.waitKey(0)
|
||||
|
||||
elif self.graph == "spec":
|
||||
stft = self.STFT(inputAudio)
|
||||
imgSpec = self.drawSpectrogram(stft)
|
||||
imgSpec = self.drawSpectrogramColorbar(imgSpec, inputAudio, samplingRate, stft)
|
||||
cv.imshow("Display window", imgSpec)
|
||||
cv.waitKey(0)
|
||||
|
||||
elif self.graph == "ampl_and_spec":
|
||||
imgAmplitude = self.drawAmplitude(inputAudio)
|
||||
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, inputAudio, samplingRate)
|
||||
|
||||
stft = self.STFT(inputAudio)
|
||||
imgSpec = self.drawSpectrogram(stft)
|
||||
imgSpec = self.drawSpectrogramColorbar(imgSpec, inputAudio, samplingRate, stft)
|
||||
|
||||
imgTotal = self.concatenateImages(imgAmplitude, imgSpec)
|
||||
cv.imshow("Display window", imgTotal)
|
||||
cv.waitKey(0)
|
||||
|
||||
elif self.draw == "dynamic":
|
||||
|
||||
if self.inputType == "file":
|
||||
self.dynamicFile(self.audio)
|
||||
|
||||
elif self.inputType == "microphone":
|
||||
self.dynamicMicrophone()
|
||||
|
||||
|
||||
def readAudioFile(self, file):
|
||||
cap = cv.VideoCapture(file)
|
||||
|
||||
params = [cv.CAP_PROP_AUDIO_STREAM, self.audioStream,
|
||||
cv.CAP_PROP_VIDEO_STREAM, -1,
|
||||
cv.CAP_PROP_AUDIO_DATA_DEPTH, cv.CV_16S]
|
||||
params = np.asarray(params)
|
||||
|
||||
cap.open(file, cv.CAP_ANY, params)
|
||||
if cap.isOpened() == False:
|
||||
print("Error : Can't read audio file: '", self.audio, "' with audioStream = ", self.audioStream)
|
||||
print("Error: problems with audio reading, check input arguments")
|
||||
exit()
|
||||
audioBaseIndex = int(cap.get(cv.CAP_PROP_AUDIO_BASE_INDEX))
|
||||
numberOfChannels = int(cap.get(cv.CAP_PROP_AUDIO_TOTAL_CHANNELS))
|
||||
|
||||
print("CAP_PROP_AUDIO_DATA_DEPTH: ", str((int(cap.get(cv.CAP_PROP_AUDIO_DATA_DEPTH)))))
|
||||
print("CAP_PROP_AUDIO_SAMPLES_PER_SECOND: ", cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
|
||||
print("CAP_PROP_AUDIO_TOTAL_CHANNELS: ", numberOfChannels)
|
||||
print("CAP_PROP_AUDIO_TOTAL_STREAMS: ", cap.get(cv.CAP_PROP_AUDIO_TOTAL_STREAMS))
|
||||
|
||||
frame = []
|
||||
frame = np.asarray(frame)
|
||||
inputAudio = []
|
||||
|
||||
while (1):
|
||||
if (cap.grab()):
|
||||
frame = []
|
||||
frame = np.asarray(frame)
|
||||
frame = cap.retrieve(frame, audioBaseIndex)
|
||||
for i in range(len(frame[1][0])):
|
||||
inputAudio.append(frame[1][0][i])
|
||||
else:
|
||||
break
|
||||
|
||||
inputAudio = np.asarray(inputAudio)
|
||||
print("Number of samples: ", len(inputAudio))
|
||||
samplingRate = int(cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
|
||||
return samplingRate, inputAudio
|
||||
|
||||
|
||||
def readAudioMicrophone(self):
|
||||
cap = cv.VideoCapture()
|
||||
|
||||
params = [cv.CAP_PROP_AUDIO_STREAM, 0, cv.CAP_PROP_VIDEO_STREAM, -1]
|
||||
params = np.asarray(params)
|
||||
|
||||
cap.open(0, cv.CAP_ANY, params)
|
||||
if cap.isOpened() == False:
|
||||
print("Error: Can't open microphone")
|
||||
print("Error: problems with audio reading, check input arguments")
|
||||
exit()
|
||||
audioBaseIndex = int(cap.get(cv.CAP_PROP_AUDIO_BASE_INDEX))
|
||||
numberOfChannels = int(cap.get(cv.CAP_PROP_AUDIO_TOTAL_CHANNELS))
|
||||
|
||||
print("CAP_PROP_AUDIO_DATA_DEPTH: ", str((int(cap.get(cv.CAP_PROP_AUDIO_DATA_DEPTH)))))
|
||||
print("CAP_PROP_AUDIO_SAMPLES_PER_SECOND: ", cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
|
||||
print("CAP_PROP_AUDIO_TOTAL_CHANNELS: ", numberOfChannels)
|
||||
print("CAP_PROP_AUDIO_TOTAL_STREAMS: ", cap.get(cv.CAP_PROP_AUDIO_TOTAL_STREAMS))
|
||||
|
||||
cvTickFreq = cv.getTickFrequency()
|
||||
sysTimeCurr = cv.getTickCount()
|
||||
sysTimePrev = sysTimeCurr
|
||||
|
||||
frame = []
|
||||
frame = np.asarray(frame)
|
||||
inputAudio = []
|
||||
|
||||
while ((sysTimeCurr - sysTimePrev) / cvTickFreq < self.microTime):
|
||||
if (cap.grab()):
|
||||
frame = []
|
||||
frame = np.asarray(frame)
|
||||
frame = cap.retrieve(frame, audioBaseIndex)
|
||||
for i in range(len(frame[1][0])):
|
||||
inputAudio.append(frame[1][0][i])
|
||||
sysTimeCurr = cv.getTickCount()
|
||||
else:
|
||||
print("Error: Grab error")
|
||||
break
|
||||
|
||||
inputAudio = np.asarray(inputAudio)
|
||||
print("Number of samples: ", len(inputAudio))
|
||||
samplingRate = int(cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
|
||||
|
||||
return samplingRate, inputAudio
|
||||
|
||||
|
||||
def drawAmplitude(self, inputAudio):
|
||||
color = (247, 111, 87)
|
||||
thickness = 5
|
||||
frameVectorRows = 500
|
||||
middle = frameVectorRows // 2
|
||||
|
||||
# usually the input data is too big, so it is necessary
|
||||
# to reduce size using interpolation of data
|
||||
frameVectorCols = 40000
|
||||
if len(inputAudio) < frameVectorCols:
|
||||
frameVectorCols = len(inputAudio)
|
||||
|
||||
img = np.zeros((frameVectorRows, frameVectorCols, 3), np.uint8)
|
||||
img += 255 # white background
|
||||
|
||||
audio = np.array(0)
|
||||
audio = cv.resize(inputAudio, (1, frameVectorCols), interpolation=cv.INTER_LINEAR)
|
||||
reshapeAudio = np.reshape(audio, (-1))
|
||||
|
||||
# normalization data by maximum element
|
||||
minCv, maxCv, _, _ = cv.minMaxLoc(reshapeAudio)
|
||||
maxElem = int(max(abs(minCv), abs(maxCv)))
|
||||
|
||||
# if all data values are zero (silence)
|
||||
if maxElem == 0:
|
||||
maxElem = 1
|
||||
for i in range(len(reshapeAudio)):
|
||||
reshapeAudio[i] = middle - reshapeAudio[i] * middle // maxElem
|
||||
|
||||
for i in range(1, frameVectorCols, 1):
|
||||
cv.line(img, (i - 1, int(reshapeAudio[i - 1])), (i, int(reshapeAudio[i])), color, thickness)
|
||||
|
||||
img = cv.resize(img, (900, 400), interpolation=cv.INTER_AREA)
|
||||
return img
|
||||
|
||||
|
||||
def drawAmplitudeScale(self, inputImg, inputAudio, samplingRate, xmin=None, xmax=None):
|
||||
# function of layout drawing for graph of volume amplitudes
|
||||
# x axis for time
|
||||
# y axis for amplitudes
|
||||
|
||||
# parameters for the new image size
|
||||
preCol = 100
|
||||
aftCol = 100
|
||||
preLine = 40
|
||||
aftLine = 50
|
||||
|
||||
frameVectorRows = inputImg.shape[0]
|
||||
frameVectorCols = inputImg.shape[1]
|
||||
|
||||
totalRows = preLine + frameVectorRows + aftLine
|
||||
totalCols = preCol + frameVectorCols + aftCol
|
||||
|
||||
imgTotal = np.zeros((totalRows, totalCols, 3), np.uint8)
|
||||
imgTotal += 255 # white background
|
||||
imgTotal[preLine: preLine + frameVectorRows, preCol: preCol + frameVectorCols] = inputImg
|
||||
|
||||
# calculating values on x axis
|
||||
if xmin is None:
|
||||
xmin = 0
|
||||
if xmax is None:
|
||||
xmax = len(inputAudio) / samplingRate
|
||||
|
||||
if xmax > self.xmarkup:
|
||||
xList = np.linspace(xmin, xmax, self.xmarkup).astype(int)
|
||||
else:
|
||||
# this case is used to display a dynamic update
|
||||
tmp = np.arange(xmin, xmax, 1).astype(int) + 1
|
||||
xList = np.concatenate((np.zeros(self.xmarkup - len(tmp)), tmp[:]), axis=None)
|
||||
|
||||
# calculating values on y axis
|
||||
ymin = np.min(inputAudio)
|
||||
ymax = np.max(inputAudio)
|
||||
yList = np.linspace(ymin, ymax, self.ymarkup)
|
||||
|
||||
# parameters for layout drawing
|
||||
textThickness = 1
|
||||
gridThickness = 1
|
||||
gridColor = (0, 0, 0)
|
||||
textColor = (0, 0, 0)
|
||||
font = cv.FONT_HERSHEY_SIMPLEX
|
||||
fontScale = 0.5
|
||||
|
||||
# horizontal axis under the graph
|
||||
cv.line(imgTotal, (preCol, totalRows - aftLine),
|
||||
(preCol + frameVectorCols, totalRows - aftLine),
|
||||
gridColor, gridThickness)
|
||||
# vertical axis for amplitude
|
||||
cv.line(imgTotal, (preCol, preLine), (preCol, preLine + frameVectorRows),
|
||||
gridColor, gridThickness)
|
||||
|
||||
# parameters for layout calculation
|
||||
serifSize = 10
|
||||
indentDownX = serifSize * 2
|
||||
indentDownY = serifSize // 2
|
||||
indentLeftX = serifSize
|
||||
indentLeftY = 2 * preCol // 3
|
||||
|
||||
# drawing layout for x axis
|
||||
numX = frameVectorCols // (self.xmarkup - 1)
|
||||
for i in range(len(xList)):
|
||||
a1 = preCol + i * numX
|
||||
a2 = frameVectorRows + preLine
|
||||
b1 = a1
|
||||
b2 = a2 + serifSize
|
||||
if self.enableGrid is True:
|
||||
d1 = a1
|
||||
d2 = preLine
|
||||
cv.line(imgTotal, (a1, a2), (d1, d2), gridColor, gridThickness)
|
||||
cv.line(imgTotal, (a1, a2), (b1, b2), gridColor, gridThickness)
|
||||
cv.putText(imgTotal, str(int(xList[i])), (b1 - indentLeftX, b2 + indentDownX),
|
||||
font, fontScale, textColor, textThickness)
|
||||
|
||||
# drawing layout for y axis
|
||||
numY = frameVectorRows // (self.ymarkup - 1)
|
||||
for i in range(len(yList)):
|
||||
a1 = preCol
|
||||
a2 = totalRows - aftLine - i * numY
|
||||
b1 = preCol - serifSize
|
||||
b2 = a2
|
||||
if self.enableGrid is True:
|
||||
d1 = preCol + frameVectorCols
|
||||
d2 = a2
|
||||
cv.line(imgTotal, (a1, a2), (d1, d2), gridColor, gridThickness)
|
||||
cv.line(imgTotal, (a1, a2), (b1, b2), gridColor, gridThickness)
|
||||
cv.putText(imgTotal, str(int(yList[i])), (b1 - indentLeftY, b2 + indentDownY),
|
||||
font, fontScale, textColor, textThickness)
|
||||
imgTotal = cv.resize(imgTotal, (self.cols, self.rows), interpolation=cv.INTER_AREA)
|
||||
return imgTotal
|
||||
|
||||
|
||||
def STFT(self, inputAudio):
|
||||
"""
|
||||
The Short-time Fourier transform (STFT), is a Fourier-related transform used to determine
|
||||
the sinusoidal frequency and phase content of local sections of a signal as it changes over
|
||||
time.
|
||||
In practice, the procedure for computing STFTs is to divide a longer time signal into
|
||||
shorter segments of equal length and then compute the Fourier transform separately on each
|
||||
shorter segment. This reveals the Fourier spectrum on each shorter segment. One then usually
|
||||
plots the changing spectra as a function of time, known as a spectrogram or waterfall plot.
|
||||
|
||||
https://en.wikipedia.org/wiki/Short-time_Fourier_transform
|
||||
"""
|
||||
|
||||
time_step = self.windLen - self.overlap
|
||||
stft = []
|
||||
|
||||
if self.windowType == "Hann":
|
||||
# https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows
|
||||
Hann_wind = []
|
||||
for i in range (1 - self.windLen, self.windLen, 2):
|
||||
Hann_wind.append(i * (0.5 + 0.5 * math.cos(math.pi * i / (self.windLen - 1))))
|
||||
Hann_wind = np.asarray(Hann_wind)
|
||||
|
||||
elif self.windowType == "Hamming":
|
||||
# https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows
|
||||
Hamming_wind = []
|
||||
for i in range (1 - self.windLen, self.windLen, 2):
|
||||
Hamming_wind.append(i * (0.53836 - 0.46164 * (math.cos(2 * math.pi * i / (self.windLen - 1)))))
|
||||
Hamming_wind = np.asarray(Hamming_wind)
|
||||
|
||||
for index in np.arange(0, len(inputAudio), time_step).astype(int):
|
||||
|
||||
section = inputAudio[index:index + self.windLen]
|
||||
zeroArray = np.zeros(self.windLen - len(section))
|
||||
section = np.concatenate((section, zeroArray), axis=None)
|
||||
|
||||
if self.windowType == "Hann":
|
||||
section *= Hann_wind
|
||||
elif self.windowType == "Hamming":
|
||||
section *= Hamming_wind
|
||||
|
||||
dst = np.empty(0)
|
||||
dst = cv.dft(section, dst, flags=cv.DFT_COMPLEX_OUTPUT)
|
||||
reshape_dst = np.reshape(dst, (-1))
|
||||
# we need only the first part of the spectrum, the second part is symmetrical
|
||||
complexArr = np.zeros(len(dst) // 4, dtype=complex)
|
||||
for i in range(len(dst) // 4):
|
||||
complexArr[i] = complex(reshape_dst[2 * i], reshape_dst[2 * i + 1])
|
||||
stft.append(np.abs(complexArr))
|
||||
|
||||
stft = np.array(stft).transpose()
|
||||
# convert elements to the decibel scale
|
||||
np.log10(stft, out=stft, where=(stft != 0.))
|
||||
return 10 * stft
|
||||
|
||||
|
||||
def drawSpectrogram(self, stft):
|
||||
|
||||
frameVectorRows = stft.shape[0]
|
||||
frameVectorCols = stft.shape[1]
|
||||
|
||||
# Normalization of image values from 0 to 255 to get more contrast image
|
||||
# and this normalization will be taken into account in the scale drawing
|
||||
colormapImageRows = 255
|
||||
|
||||
imgSpec = np.zeros((frameVectorRows, frameVectorCols, 3), np.uint8)
|
||||
stftMat = np.zeros((frameVectorRows, frameVectorCols), np.float64)
|
||||
cv.normalize(stft, stftMat, 1.0, 0.0, cv.NORM_INF)
|
||||
|
||||
for i in range(frameVectorRows):
|
||||
for j in range(frameVectorCols):
|
||||
imgSpec[frameVectorRows - i - 1, j] = int(stftMat[i][j] * colormapImageRows)
|
||||
|
||||
imgSpec = cv.applyColorMap(imgSpec, cv.COLORMAP_INFERNO)
|
||||
imgSpec = cv.resize(imgSpec, (900, 400), interpolation=cv.INTER_LINEAR)
|
||||
return imgSpec
|
||||
|
||||
|
||||
def drawSpectrogramColorbar(self, inputImg, inputAudio, samplingRate, stft, xmin=None, xmax=None):
|
||||
# function of layout drawing for the three-dimensional graph of the spectrogram
|
||||
# x axis for time
|
||||
# y axis for frequencies
|
||||
# z axis for magnitudes of frequencies shown by color scale
|
||||
|
||||
# parameters for the new image size
|
||||
preCol = 100
|
||||
aftCol = 100
|
||||
preLine = 40
|
||||
aftLine = 50
|
||||
colColor = 20
|
||||
ind_col = 20
|
||||
|
||||
frameVectorRows = inputImg.shape[0]
|
||||
frameVectorCols = inputImg.shape[1]
|
||||
|
||||
totalRows = preLine + frameVectorRows + aftLine
|
||||
totalCols = preCol + frameVectorCols + aftCol + colColor
|
||||
|
||||
imgTotal = np.zeros((totalRows, totalCols, 3), np.uint8)
|
||||
imgTotal += 255 # white background
|
||||
imgTotal[preLine: preLine + frameVectorRows, preCol: preCol + frameVectorCols] = inputImg
|
||||
|
||||
# colorbar image due to drawSpectrogram(..) picture has been normalised from 255 to 0,
|
||||
# so here colorbar has values from 255 to 0
|
||||
colorArrSize = 256
|
||||
imgColorBar = np.zeros((colorArrSize, colColor, 1), np.uint8)
|
||||
|
||||
for i in range(colorArrSize):
|
||||
imgColorBar[i] += colorArrSize - 1 - i
|
||||
|
||||
imgColorBar = cv.applyColorMap(imgColorBar, cv.COLORMAP_INFERNO)
|
||||
imgColorBar = cv.resize(imgColorBar, (colColor, frameVectorRows), interpolation=cv.INTER_AREA) #
|
||||
|
||||
imgTotal[preLine: preLine + frameVectorRows,
|
||||
preCol + frameVectorCols + ind_col:
|
||||
preCol + frameVectorCols + ind_col + colColor] = imgColorBar
|
||||
|
||||
# calculating values on x axis
|
||||
if xmin is None:
|
||||
xmin = 0
|
||||
if xmax is None:
|
||||
xmax = len(inputAudio) / samplingRate
|
||||
if xmax > self.xmarkup:
|
||||
xList = np.linspace(xmin, xmax, self.xmarkup).astype(int)
|
||||
else:
|
||||
# this case is used to display a dynamic update
|
||||
tmpXList = np.arange(xmin, xmax, 1).astype(int) + 1
|
||||
xList = np.concatenate((np.zeros(self.xmarkup - len(tmpXList)), tmpXList[:]), axis=None)
|
||||
|
||||
# calculating values on y axis
|
||||
# according to the Nyquist sampling theorem,
|
||||
# signal should posses frequencies equal to half of sampling rate
|
||||
ymin = 0
|
||||
ymax = int(samplingRate / 2.)
|
||||
yList = np.linspace(ymin, ymax, self.ymarkup).astype(int)
|
||||
|
||||
# calculating values on z axis
|
||||
zList = np.linspace(np.min(stft), np.max(stft), self.zmarkup)
|
||||
|
||||
# parameters for layout drawing
|
||||
textThickness = 1
|
||||
textColor = (0, 0, 0)
|
||||
gridThickness = 1
|
||||
gridColor = (0, 0, 0)
|
||||
font = cv.FONT_HERSHEY_SIMPLEX
|
||||
fontScale = 0.5
|
||||
|
||||
serifSize = 10
|
||||
indentDownX = serifSize * 2
|
||||
indentDownY = serifSize // 2
|
||||
indentLeftX = serifSize
|
||||
indentLeftY = 2 * preCol // 3
|
||||
|
||||
# horizontal axis
|
||||
cv.line(imgTotal, (preCol, totalRows - aftLine), (preCol + frameVectorCols, totalRows - aftLine),
|
||||
gridColor, gridThickness)
|
||||
# vertical axis
|
||||
cv.line(imgTotal, (preCol, preLine), (preCol, preLine + frameVectorRows),
|
||||
gridColor, gridThickness)
|
||||
|
||||
# drawing layout for x axis
|
||||
numX = frameVectorCols // (self.xmarkup - 1)
|
||||
for i in range(len(xList)):
|
||||
a1 = preCol + i * numX
|
||||
a2 = frameVectorRows + preLine
|
||||
b1 = a1
|
||||
b2 = a2 + serifSize
|
||||
cv.line(imgTotal, (a1, a2), (b1, b2), gridColor, gridThickness)
|
||||
cv.putText(imgTotal, str(int(xList[i])), (b1 - indentLeftX, b2 + indentDownX),
|
||||
font, fontScale, textColor, textThickness)
|
||||
|
||||
# drawing layout for y axis
|
||||
numY = frameVectorRows // (self.ymarkup - 1)
|
||||
for i in range(len(yList)):
|
||||
a1 = preCol
|
||||
a2 = totalRows - aftLine - i * numY
|
||||
b1 = preCol - serifSize
|
||||
b2 = a2
|
||||
cv.line(imgTotal, (a1, a2), (b1, b2), gridColor, gridThickness)
|
||||
cv.putText(imgTotal, str(int(yList[i])), (b1 - indentLeftY, b2 + indentDownY),
|
||||
font, fontScale, textColor, textThickness)
|
||||
|
||||
# drawing layout for z axis
|
||||
numZ = frameVectorRows // (self.zmarkup - 1)
|
||||
for i in range(len(zList)):
|
||||
a1 = preCol + frameVectorCols + ind_col + colColor
|
||||
a2 = totalRows - aftLine - i * numZ
|
||||
b1 = a1 + serifSize
|
||||
b2 = a2
|
||||
cv.line(imgTotal, (a1, a2), (b1, b2), gridColor, gridThickness)
|
||||
cv.putText(imgTotal, str(int(zList[i])), (b1 + 10, b2 + indentDownY),
|
||||
font, fontScale, textColor, textThickness)
|
||||
imgTotal = cv.resize(imgTotal, (self.cols, self.rows), interpolation=cv.INTER_AREA)
|
||||
return imgTotal
|
||||
|
||||
|
||||
def concatenateImages(self, img1, img2):
|
||||
# first image will be under the second image
|
||||
totalRows = img1.shape[0] + img2.shape[0]
|
||||
totalCols = max(img1.shape[1], img2.shape[1])
|
||||
|
||||
# if images columns do not match, the difference is filled in white
|
||||
imgTotal = np.zeros((totalRows, totalCols, 3), np.uint8)
|
||||
imgTotal += 255
|
||||
|
||||
imgTotal[:img1.shape[0], :img1.shape[1]] = img1
|
||||
imgTotal[img2.shape[0]:, :img2.shape[1]] = img2
|
||||
|
||||
return imgTotal
|
||||
|
||||
|
||||
def dynamicFile(self, file):
|
||||
cap = cv.VideoCapture(file)
|
||||
params = [cv.CAP_PROP_AUDIO_STREAM, self.audioStream,
|
||||
cv.CAP_PROP_VIDEO_STREAM, -1,
|
||||
cv.CAP_PROP_AUDIO_DATA_DEPTH, cv.CV_16S]
|
||||
params = np.asarray(params)
|
||||
|
||||
cap.open(file, cv.CAP_ANY, params)
|
||||
if cap.isOpened() == False:
|
||||
print("ERROR! Can't to open file")
|
||||
return
|
||||
|
||||
audioBaseIndex = int(cap.get(cv.CAP_PROP_AUDIO_BASE_INDEX))
|
||||
numberOfChannels = int(cap.get(cv.CAP_PROP_AUDIO_TOTAL_CHANNELS))
|
||||
samplingRate = int(cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
|
||||
|
||||
print("CAP_PROP_AUDIO_DATA_DEPTH: ", str((int(cap.get(cv.CAP_PROP_AUDIO_DATA_DEPTH)))))
|
||||
print("CAP_PROP_AUDIO_SAMPLES_PER_SECOND: ", cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
|
||||
print("CAP_PROP_AUDIO_TOTAL_CHANNELS: ", numberOfChannels)
|
||||
print("CAP_PROP_AUDIO_TOTAL_STREAMS: ", cap.get(cv.CAP_PROP_AUDIO_TOTAL_STREAMS))
|
||||
|
||||
step = int(self.updateTime * samplingRate)
|
||||
frameSize = int(self.frameSizeTime * samplingRate)
|
||||
# since the dimensional grid is counted in integer seconds,
|
||||
# if duration of audio frame is less than xmarkup, to avoid an incorrect display,
|
||||
# xmarkup will be taken equal to duration
|
||||
if self.frameSizeTime <= self.xmarkup:
|
||||
self.xmarkup = self.frameSizeTime
|
||||
|
||||
buffer = []
|
||||
section = np.zeros(frameSize, dtype=np.int16)
|
||||
currentSamples = 0
|
||||
|
||||
while (1):
|
||||
if (cap.grab()):
|
||||
frame = []
|
||||
frame = np.asarray(frame)
|
||||
frame = cap.retrieve(frame, audioBaseIndex)
|
||||
|
||||
for i in range(len(frame[1][0])):
|
||||
buffer.append(frame[1][0][i])
|
||||
|
||||
buffer_size = len(buffer)
|
||||
if (buffer_size >= step):
|
||||
|
||||
section = list(section)
|
||||
currentSamples += step
|
||||
|
||||
del section[0:step]
|
||||
section.extend(buffer[0:step])
|
||||
del buffer[0:step]
|
||||
|
||||
section = np.asarray(section)
|
||||
|
||||
if currentSamples < frameSize:
|
||||
xmin = 0
|
||||
xmax = (currentSamples) / samplingRate
|
||||
else:
|
||||
xmin = (currentSamples - frameSize) / samplingRate + 1
|
||||
xmax = (currentSamples) / samplingRate
|
||||
|
||||
if self.graph == "ampl":
|
||||
imgAmplitude = self.drawAmplitude(section)
|
||||
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, section, samplingRate, xmin, xmax)
|
||||
cv.imshow("Display amplitude graph", imgAmplitude)
|
||||
cv.waitKey(self.waitTime)
|
||||
|
||||
elif self.graph == "spec":
|
||||
stft = self.STFT(section)
|
||||
imgSpec = self.drawSpectrogram(stft)
|
||||
imgSpec = self.drawSpectrogramColorbar(imgSpec, section, samplingRate, stft, xmin, xmax)
|
||||
cv.imshow("Display spectrogram", imgSpec)
|
||||
cv.waitKey(self.waitTime)
|
||||
|
||||
elif self.graph == "ampl_and_spec":
|
||||
|
||||
imgAmplitude = self.drawAmplitude(section)
|
||||
stft = self.STFT(section)
|
||||
imgSpec = self.drawSpectrogram(stft)
|
||||
|
||||
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, section, samplingRate, xmin, xmax)
|
||||
imgSpec = self.drawSpectrogramColorbar(imgSpec, section, samplingRate, stft, xmin, xmax)
|
||||
|
||||
imgTotal = self.concatenateImages(imgAmplitude, imgSpec)
|
||||
cv.imshow("Display amplitude graph and spectrogram", imgTotal)
|
||||
cv.waitKey(self.waitTime)
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
def dynamicMicrophone(self):
|
||||
cap = cv.VideoCapture()
|
||||
params = [cv.CAP_PROP_AUDIO_STREAM, 0, cv.CAP_PROP_VIDEO_STREAM, -1]
|
||||
params = np.asarray(params)
|
||||
|
||||
cap.open(0, cv.CAP_ANY, params)
|
||||
if cap.isOpened() == False:
|
||||
print("ERROR! Can't to open file")
|
||||
return
|
||||
audioBaseIndex = int(cap.get(cv.CAP_PROP_AUDIO_BASE_INDEX))
|
||||
numberOfChannels = int(cap.get(cv.CAP_PROP_AUDIO_TOTAL_CHANNELS))
|
||||
|
||||
print("CAP_PROP_AUDIO_DATA_DEPTH: ", str((int(cap.get(cv.CAP_PROP_AUDIO_DATA_DEPTH)))))
|
||||
print("CAP_PROP_AUDIO_SAMPLES_PER_SECOND: ", cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
|
||||
print("CAP_PROP_AUDIO_TOTAL_CHANNELS: ", numberOfChannels)
|
||||
print("CAP_PROP_AUDIO_TOTAL_STREAMS: ", cap.get(cv.CAP_PROP_AUDIO_TOTAL_STREAMS))
|
||||
|
||||
frame = []
|
||||
frame = np.asarray(frame)
|
||||
samplingRate = int(cap.get(cv.CAP_PROP_AUDIO_SAMPLES_PER_SECOND))
|
||||
|
||||
step = int(self.updateTime * samplingRate)
|
||||
frameSize = int(self.frameSizeTime * samplingRate)
|
||||
self.xmarkup = self.frameSizeTime
|
||||
|
||||
currentSamples = 0
|
||||
|
||||
buffer = []
|
||||
section = np.zeros(frameSize, dtype=np.int16)
|
||||
|
||||
cvTickFreq = cv.getTickFrequency()
|
||||
sysTimeCurr = cv.getTickCount()
|
||||
sysTimePrev = sysTimeCurr
|
||||
self.waitTime = self.updateTime * 1000
|
||||
while ((sysTimeCurr - sysTimePrev) / cvTickFreq < self.microTime):
|
||||
if (cap.grab()):
|
||||
frame = []
|
||||
frame = np.asarray(frame)
|
||||
frame = cap.retrieve(frame, audioBaseIndex)
|
||||
|
||||
for i in range(len(frame[1][0])):
|
||||
buffer.append(frame[1][0][i])
|
||||
|
||||
sysTimeCurr = cv.getTickCount()
|
||||
buffer_size = len(buffer)
|
||||
if (buffer_size >= step):
|
||||
|
||||
section = list(section)
|
||||
currentSamples += step
|
||||
|
||||
del section[0:step]
|
||||
section.extend(buffer[0:step])
|
||||
del buffer[0:step]
|
||||
|
||||
section = np.asarray(section)
|
||||
|
||||
if currentSamples < frameSize:
|
||||
xmin = 0
|
||||
xmax = (currentSamples) / samplingRate
|
||||
else:
|
||||
xmin = (currentSamples - frameSize) / samplingRate + 1
|
||||
xmax = (currentSamples) / samplingRate
|
||||
|
||||
if self.graph == "ampl":
|
||||
imgAmplitude = self.drawAmplitude(section)
|
||||
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, section, samplingRate, xmin, xmax)
|
||||
cv.imshow("Display amplitude graph", imgAmplitude)
|
||||
cv.waitKey(self.waitTime)
|
||||
|
||||
elif self.graph == "spec":
|
||||
stft = self.STFT(section)
|
||||
imgSpec = self.drawSpectrogram(stft)
|
||||
imgSpec = self.drawSpectrogramColorbar(imgSpec, section, samplingRate, stft, xmin, xmax)
|
||||
cv.imshow("Display spectrogram", imgSpec)
|
||||
cv.waitKey(self.waitTime)
|
||||
|
||||
elif self.graph == "ampl_and_spec":
|
||||
imgAmplitude = self.drawAmplitude(section)
|
||||
stft = self.STFT(section)
|
||||
imgSpec = self.drawSpectrogram(stft)
|
||||
|
||||
imgAmplitude = self.drawAmplitudeScale(imgAmplitude, section, samplingRate, xmin, xmax)
|
||||
imgSpec = self.drawSpectrogramColorbar(imgSpec, section, samplingRate, stft, xmin, xmax)
|
||||
|
||||
imgTotal = self.concatenateImages(imgAmplitude, imgSpec)
|
||||
cv.imshow("Display amplitude graph and spectrogram", imgTotal)
|
||||
cv.waitKey(self.waitTime)
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
def initAndCheckArgs(self, args):
|
||||
if args.inputType != "file" and args.inputType != "microphone":
|
||||
print("Error: ", args.inputType, " input method doesnt exist")
|
||||
return False
|
||||
if args.draw != "static" and args.draw != "dynamic":
|
||||
print("Error: ", args.draw, " draw type doesnt exist")
|
||||
return False
|
||||
if args.graph != "ampl" and args.graph != "spec" and args.graph != "ampl_and_spec":
|
||||
print("Error: ", args.graph, " type of graph doesnt exist")
|
||||
return False
|
||||
if args.windowType != "Rect" and args.windowType != "Hann" and args.windowType != "Hamming":
|
||||
print("Error: ", args.windowType, " type of window doesnt exist")
|
||||
return False
|
||||
if args.windLen <= 0:
|
||||
print("Error: windLen = ", args.windLen, " - incorrect value. Must be > 0")
|
||||
return False
|
||||
if args.overlap <= 0:
|
||||
print("Error: overlap = ", args.overlap, " - incorrect value. Must be > 0")
|
||||
return False
|
||||
if args.rows <= 0:
|
||||
print("Error: rows = ", args.rows, " - incorrect value. Must be > 0")
|
||||
return False
|
||||
if args.cols <= 0:
|
||||
print("Error: cols = ", args.cols, " - incorrect value. Must be > 0")
|
||||
return False
|
||||
if args.xmarkup < 2:
|
||||
print("Error: xmarkup = ", args.xmarkup, " - incorrect value. Must be >= 2")
|
||||
return False
|
||||
if args.ymarkup < 2:
|
||||
print("Error: ymarkup = ", args.ymarkup, " - incorrect value. Must be >= 2")
|
||||
return False
|
||||
if args.zmarkup < 2:
|
||||
print("Error: zmarkup = ", args.zmarkup, " - incorrect value. Must be >= 2")
|
||||
return False
|
||||
if args.microTime <= 0:
|
||||
print("Error: microTime = ", args.microTime, " - incorrect value. Must be > 0")
|
||||
return False
|
||||
if args.frameSizeTime <= 0:
|
||||
print("Error: frameSizeTime = ", args.frameSizeTime, " - incorrect value. Must be > 0")
|
||||
return False
|
||||
if args.updateTime <= 0:
|
||||
print("Error: updateTime = ", args.updateTime, " - incorrect value. Must be > 0")
|
||||
return False
|
||||
if args.waitTime < 0:
|
||||
print("Error: waitTime = ", args.waitTime, " - incorrect value. Must be >= 0")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description='''this sample draws a volume graph and/or spectrogram of audio/video files and microphone\nDefault usage: ./Spectrogram.exe''')
|
||||
|
||||
parser.add_argument("-i", "--inputType", dest="inputType", type=str, default="file", help="file or microphone")
|
||||
parser.add_argument("-d", "--draw", dest="draw", type=str, default="static",
|
||||
help="type of drawing: static - for plotting graph(s) across the entire input audio; dynamic - for plotting graph(s) in a time-updating window")
|
||||
parser.add_argument("-g", "--graph", dest="graph", type=str, default="ampl_and_spec",
|
||||
help="type of graph: amplitude graph or/and spectrogram. Please use tags below : ampl - draw the amplitude graph; spec - draw the spectrogram; ampl_and_spec - draw the amplitude graph and spectrogram on one image under each other")
|
||||
|
||||
parser.add_argument("-a", "--audio", dest="audio", type=str, default='Megamind.avi',
|
||||
help="name and path to file")
|
||||
parser.add_argument("-s", "--audioStream", dest="audioStream", type=int, default=1,
|
||||
help=" CAP_PROP_AUDIO_STREAM value")
|
||||
|
||||
parser.add_argument("-t", '--windowType', dest="windowType", type=str, default="Rect",
|
||||
help="type of window for STFT. Please use tags below : Rect/Hann/Hamming")
|
||||
parser.add_argument("-l", '--windLen', dest="windLen", type=int, default=256, help="size of window for STFT")
|
||||
parser.add_argument("-o", '--overlap', dest="overlap", type=int, default=128, help="overlap of windows for STFT")
|
||||
|
||||
parser.add_argument("-gd", '--grid', dest="enableGrid", type=bool, default=False, help="grid on amplitude graph(on/off)")
|
||||
|
||||
parser.add_argument("-r", '--rows', dest="rows", type=int, default=400, help="rows of output image")
|
||||
parser.add_argument("-c", '--cols', dest="cols", type=int, default=900, help="cols of output image")
|
||||
|
||||
parser.add_argument("-x", '--xmarkup', dest="xmarkup", type=int, default=5,
|
||||
help="number of x axis divisions (time asix)")
|
||||
parser.add_argument("-y", '--ymarkup', dest="ymarkup", type=int, default=5,
|
||||
help="number of y axis divisions (frequency or/and amplitude axis)") # ?
|
||||
parser.add_argument("-z", '--zmarkup', dest="zmarkup", type=int, default=5,
|
||||
help="number of z axis divisions (colorbar)") # ?
|
||||
|
||||
parser.add_argument("-m", '--microTime', dest="microTime", type=int, default=20,
|
||||
help="time of recording audio with microphone in seconds")
|
||||
parser.add_argument("-f", '--frameSizeTime', dest="frameSizeTime", type=int, default=5,
|
||||
help="size of sliding window in seconds")
|
||||
parser.add_argument("-u", '--updateTime', dest="updateTime", type=int, default=1,
|
||||
help="update time of sliding window in seconds")
|
||||
parser.add_argument("-w", '--waitTime', dest="waitTime", type=int, default=10,
|
||||
help="parameter to cv.waitKey() for dynamic update, takes values in milliseconds")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
AudioDrawing(args).Draw()
|
||||
@@ -86,6 +86,7 @@ def explore_match(win, img1, img2, kp_pairs, status = None, H = None):
|
||||
|
||||
if status is None:
|
||||
status = np.ones(len(kp_pairs), np.bool_)
|
||||
status = status.reshape((len(kp_pairs), 1))
|
||||
p1, p2 = [], [] # python 2 / python 3 change of zip unpacking
|
||||
for kpp in kp_pairs:
|
||||
p1.append(np.int32(kpp[0].pt))
|
||||
|
||||
@@ -36,7 +36,7 @@ except (AttributeError, cv.error) as e:
|
||||
# if SURF not available, ORB is default
|
||||
FEATURES_FIND_CHOICES['orb'] = cv.ORB.create
|
||||
try:
|
||||
FEATURES_FIND_CHOICES['sift'] = cv.xfeatures2d_SIFT.create
|
||||
FEATURES_FIND_CHOICES['sift'] = cv.SIFT_create
|
||||
except AttributeError:
|
||||
print("SIFT not available")
|
||||
try:
|
||||
@@ -436,7 +436,7 @@ def main():
|
||||
sizes = []
|
||||
blender = None
|
||||
timelapser = None
|
||||
# https://github.com/opencv/opencv/blob/master/samples/cpp/stitching_detailed.cpp#L725 ?
|
||||
# https://github.com/opencv/opencv/blob/5.x/samples/cpp/stitching_detailed.cpp#L725 ?
|
||||
for idx, name in enumerate(img_names):
|
||||
full_img = cv.imread(name)
|
||||
if not is_compose_scale_set:
|
||||
|
||||
@@ -24,7 +24,7 @@ mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
|
||||
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])
|
||||
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
|
||||
|
||||
# Setup the termination criteria, either 10 iteration or move by atleast 1 pt
|
||||
# Setup the termination criteria, either 10 iteration or move by at least 1 pt
|
||||
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )
|
||||
|
||||
while(1):
|
||||
|
||||
@@ -24,7 +24,7 @@ mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
|
||||
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])
|
||||
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
|
||||
|
||||
# Setup the termination criteria, either 10 iteration or move by atleast 1 pt
|
||||
# Setup the termination criteria, either 10 iteration or move by at least 1 pt
|
||||
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )
|
||||
|
||||
while(1):
|
||||
|
||||
@@ -17,12 +17,12 @@ feature_params = dict( maxCorners = 100,
|
||||
blockSize = 7 )
|
||||
|
||||
# Parameters for lucas kanade optical flow
|
||||
lk_params = dict( winSize = (15,15),
|
||||
lk_params = dict( winSize = (15, 15),
|
||||
maxLevel = 2,
|
||||
criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))
|
||||
|
||||
# Create some random colors
|
||||
color = np.random.randint(0,255,(100,3))
|
||||
color = np.random.randint(0, 255, (100, 3))
|
||||
|
||||
# Take first frame and find corners in it
|
||||
ret, old_frame = cap.read()
|
||||
@@ -33,7 +33,11 @@ p0 = cv.goodFeaturesToTrack(old_gray, mask = None, **feature_params)
|
||||
mask = np.zeros_like(old_frame)
|
||||
|
||||
while(1):
|
||||
ret,frame = cap.read()
|
||||
ret, frame = cap.read()
|
||||
if not ret:
|
||||
print('No frames grabbed!')
|
||||
break
|
||||
|
||||
frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# calculate optical flow
|
||||
@@ -45,18 +49,20 @@ while(1):
|
||||
good_old = p0[st==1]
|
||||
|
||||
# draw the tracks
|
||||
for i,(new,old) in enumerate(zip(good_new, good_old)):
|
||||
a,b = new.ravel()
|
||||
c,d = old.ravel()
|
||||
mask = cv.line(mask, (int(a),int(b)),(int(c),int(d)), color[i].tolist(), 2)
|
||||
frame = cv.circle(frame,(int(a),int(b)),5,color[i].tolist(),-1)
|
||||
img = cv.add(frame,mask)
|
||||
for i, (new, old) in enumerate(zip(good_new, good_old)):
|
||||
a, b = new.ravel()
|
||||
c, d = old.ravel()
|
||||
mask = cv.line(mask, (int(a), int(b)), (int(c), int(d)), color[i].tolist(), 2)
|
||||
frame = cv.circle(frame, (int(a), int(b)), 5, color[i].tolist(), -1)
|
||||
img = cv.add(frame, mask)
|
||||
|
||||
cv.imshow('frame',img)
|
||||
cv.imshow('frame', img)
|
||||
k = cv.waitKey(30) & 0xff
|
||||
if k == 27:
|
||||
break
|
||||
|
||||
# Now update the previous frame and previous points
|
||||
old_gray = frame_gray.copy()
|
||||
p0 = good_new.reshape(-1,1,2)
|
||||
p0 = good_new.reshape(-1, 1, 2)
|
||||
|
||||
cv.destroyAllWindows()
|
||||
|
||||
@@ -2,22 +2,28 @@ import numpy as np
|
||||
import cv2 as cv
|
||||
cap = cv.VideoCapture(cv.samples.findFile("vtest.avi"))
|
||||
ret, frame1 = cap.read()
|
||||
prvs = cv.cvtColor(frame1,cv.COLOR_BGR2GRAY)
|
||||
prvs = cv.cvtColor(frame1, cv.COLOR_BGR2GRAY)
|
||||
hsv = np.zeros_like(frame1)
|
||||
hsv[...,1] = 255
|
||||
hsv[..., 1] = 255
|
||||
while(1):
|
||||
ret, frame2 = cap.read()
|
||||
next = cv.cvtColor(frame2,cv.COLOR_BGR2GRAY)
|
||||
flow = cv.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
|
||||
mag, ang = cv.cartToPolar(flow[...,0], flow[...,1])
|
||||
hsv[...,0] = ang*180/np.pi/2
|
||||
hsv[...,2] = cv.normalize(mag,None,0,255,cv.NORM_MINMAX)
|
||||
bgr = cv.cvtColor(hsv,cv.COLOR_HSV2BGR)
|
||||
cv.imshow('frame2',bgr)
|
||||
if not ret:
|
||||
print('No frames grabbed!')
|
||||
break
|
||||
|
||||
next = cv.cvtColor(frame2, cv.COLOR_BGR2GRAY)
|
||||
flow = cv.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
|
||||
mag, ang = cv.cartToPolar(flow[..., 0], flow[..., 1])
|
||||
hsv[..., 0] = ang*180/np.pi/2
|
||||
hsv[..., 2] = cv.normalize(mag, None, 0, 255, cv.NORM_MINMAX)
|
||||
bgr = cv.cvtColor(hsv, cv.COLOR_HSV2BGR)
|
||||
cv.imshow('frame2', bgr)
|
||||
k = cv.waitKey(30) & 0xff
|
||||
if k == 27:
|
||||
break
|
||||
elif k == ord('s'):
|
||||
cv.imwrite('opticalfb.png',frame2)
|
||||
cv.imwrite('opticalhsv.png',bgr)
|
||||
cv.imwrite('opticalfb.png', frame2)
|
||||
cv.imwrite('opticalhsv.png', bgr)
|
||||
prvs = next
|
||||
|
||||
cv.destroyAllWindows()
|
||||
|
||||
@@ -20,7 +20,7 @@ int main(void)
|
||||
// Number of experiment runs
|
||||
int no_runs = 2;
|
||||
|
||||
// https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html
|
||||
// https://docs.opencv.org/5.x/d3/d63/classcv_1_1Mat.html
|
||||
cv::Mat src_new(IMG_ROWS, IMG_COLS, CV_8UC1, (void *)raw_pixels);
|
||||
|
||||
// Set parameters
|
||||
|
||||
@@ -20,7 +20,7 @@ int main(void)
|
||||
// Number of experiment runs
|
||||
int no_runs = 2;
|
||||
|
||||
// https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html
|
||||
// https://docs.opencv.org/5.x/d3/d63/classcv_1_1Mat.html
|
||||
cv::Mat src(IMG_ROWS, IMG_COLS, CV_8UC1, (void *)raw_pixels);
|
||||
|
||||
// Run calc Hist
|
||||
|
||||
Reference in New Issue
Block a user