People head detection code and performance of Opencv 4 compared to opencv 3.2
Opencv 4.0 is released, people head detection compared to opencv 3.2
I am working with opencv for almost a 6 years. It is 3.5 years since the 3.0. The journey driven by DNN, new ideas, algorithms and optimization is breathtaking. Thanks to all contributors. Here is my point of view to opencv 4.0. The video comparison of opencv 4 and 3.2 with head and shoulders detection performance at the end of the article with sample code.
Opencv 4.0 main changes
C++11 is one of the main changes that will programmer realize at the first. This brings a lot of advantages to write safer and stable code. Smart pointers in C++11 and many features of the standard library helps to write code safer and with better performance. The reinventing the wheel is a weakness of all programmers. Better is know what is already available in various libraries and use it. The 30 years of sorting, algorithm and memory handling do not wait for application programmers reinvent.
Opencv 4.0 C API removed
It is mentioned removed C API from 1.x. I need to dive deeper into this. I used this API in FFmpeg combination with opencv long long time ago. Sometimes, I like old C more than C++. I get the point. I can take it. The maintain the C API there is no point.
OPENCV 4.0 XML YAML and JSON loading and storing
The configuration parsing of DNN and various other algorithm is key for automation and basically most of the annoying parts of the program. If you ever write your own parser for CSV, XML or JSON you know what is the most boring experience in programming :).
Opencv 4.0 G-API
New module G-API is an engine for very efficient graph-based image processing pipelines. This looks interesting and can speed up performance and as well development. An example can be to prepare image into some specific stage. Basically, G api is input-output pipeline and between input and output, you can perform very fast transformation of your image. It is as well very efficient from the point of memory management and access. Following example define pipeline from an input image to resized image to grayscale image,. If you want to use this pipeline in the code just write cv::GComputation ac(in, out);. The all the pipeline from input and output will be performed.
cv::GMat in;
cv::GMat vga = cv::gapi::resize(in, cv::Size(), 0.5, 0.5);
cv::GMat out = cv::gapi::BGR2Gray(vga);
cv::GComputation ac(in, out);
This can be very cool features. I will learn more about and prepare some of my thoughts about G-API.
Opencv 4.0 DNN module
Dnn module now includes experimental Vulkan backend. Vulkan is cross-platform 3D graphics computation API. New alternative against OpenGL and Direct3D. This can speed up processing of some layers in DNN as in case of 3D graphics. The representations and models are pretty much the same from the internal point of view.
Opencv 4 vs 3.2 Opencv performance
Both are optimized as much as possible for I7 HW without GPU. The development does not focus exactly on LBP cascade detectMultiscale. This both opencv tasks performing really similar on this concrete problem.
Opencv 4 cmake build configuration
This is just my example of cmake configuration. I am not using any special magic right now to build opencv 4.0.0.
General configuration for OpenCV 4.0.0 =====================================
Install to: C:/opencv4build/install
-----------------------------------------------------------------
Version control: unknown
Timestamp: 2018-11-25T10:16:09Z
Host: Windows 10.0.17134 AMD64
CMake: 3.13.0-rc2
CMake generator: Visual Studio 15 2017 Win64
CMake build tool: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/MSBuild/15.0/Bin/MSBuild.exe
MSVC: 1915
CPU/HW features:
Baseline: SSE SSE2 SSE3
requested: SSE3
Dispatched code generation: SSE4_1 SSE4_2 FP16 AVX AVX2
requested: SSE4_1 SSE4_2 AVX FP16 AVX2 AVX512_SKX
SSE4_1 (7 files): + SSSE3 SSE4_1
SSE4_2 (2 files): + SSSE3 SSE4_1 POPCNT SSE4_2
FP16 (1 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 AVX
AVX (5 files): + SSSE3 SSE4_1 POPCNT SSE4_2 AVX
AVX2 (13 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2
FFMPEG: YES (prebuilt binaries)
avcodec: YES (ver 58.35.100)
avformat: YES (ver 58.20.100)
avutil: YES (ver 56.22.100)
swscale: YES (ver 5.3.100)
avresample: YES (ver 4.0.0)
DirectShow: YES
Media Foundation: YES
Parallel framework: Concurrency
Trace: YES (with Intel ITT)
Other third-party libraries:
Intel IPP: 2019.0.0 Gold [2019.0.0]
Intel IPP IW: sources (2019.0.0)
-----------------------------------------------------------------
Code of opencv 4 performance comparison sample
If you want to run the code. The problem is to use own detection cascade instead of cascade25.xml. This cascade is my own train to detect head and shoulders mainly from top view. This is not even top view but still there are some detections. Parameters (detectorBody.detectMultiScale(img, human, 1.4, 3, 0 | 1, Size(30,30), Size(120, 120));. ) are also not optimal but perform very fast on CPU and for comparison purpuse only.
Opencv 3 vs Opencv 4 diferrence
Warning focus on difference between opencv 3 and opencv 4CV_CAP_OPENNI_BGR_IMAGE as CAP_OPENNI_BGR_IMAGE
CV_BGR2GRAY as COLOR_BGR2GRAY
outputVideo.open("video3.wmv", CV_FOURCC('W', 'M', 'V', '2'), cap.get(CV_CAP_PROP_FPS), Size(640, 480), true);
opencv 4
outputVideo.open("video3.wmv", VideoWriter::fourcc('W', 'M', 'V', '2'), cap.get(CAP_PROP_FPS), Size(640, 480), true);
Opencv 4.0 head detection, tutorial code example
Almost everithink is the same. This is the reason why there is only function det(). Focus on parts described in Opencv 3 vs Opencv 4 diferrence chapter.
#include "pch.h"
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <fstream>
#include <sstream>
#include "opencv2/objdetect\objdetect.hpp"
using namespace cv;
using namespace std;
string to_strin(double x) {
ostringstream x_convert;
x_convert << x;
return x_convert.str();
}
int det()
{
// prepare video input
VideoCapture cap("mo.mov");
// prepare video output
VideoWriter outputVideo;
outputVideo.open("video3.wmv", VideoWriter::fourcc('W', 'M', 'V', '2'),
cap.get(CAP_PROP_FPS), Size(640, 480), true);
// prepare cascadeClassifier
CascadeClassifier detectorBody;
// !! Put your cascade or opencv cascede into project folder !!
string cascadeName1 = "cascade25.xml";
// Load cascade into CascadeClassifier
bool loaded1 = detectorBody.load(cascadeName1);
// Basic video input loop
for (;;)
{
bool Is = cap.grab();
if (Is == false) {
cout << "Video Capture Fail" << endl;
break;
}
else {
// Just for measure time
const clock_t begin_time = clock();
// Store results in these 2 vectors
vector human;
vector upperBody;
// prepare 2 Mat container
Mat img;
Mat original;
// capture frame from video file
cap.retrieve(img, CAP_OPENNI_BGR_IMAGE);
// Resize image if you want with same size as your VideoWriter
resize(img, img, Size(640, 480));
// Store original colored image
img.copyTo(original);
// color to gray image
cvtColor(img, img, COLOR_BGR2GRAY);
// detect people, more remarks in performace section
detectorBody.detectMultiScale(img, human, 1.4, 3,
0 | 1, Size(30, 30), Size(120, 120));
// Draw results from detectorBody into original colored image
if (human.size() > 0) {
for (int gg = 0; gg < human.size(); gg++) {
rectangle(original, human[gg].tl(),
human[gg].br(), Scalar(0, 0, 255), 2, 8, 0);
}
}
// measure time as current - begin_time
clock_t diff = clock() - begin_time;
// convert time into string
//char buffer[126];
//sprintf(buffer, "%d", diff);
// display TIME ms on original image
double ms = (double)diff;
string mmm = to_strin(ms);
putText(original, mmm, Point(100, 20), 1, 2,
Scalar(255, 255, 255), 2, 8, 0);
putText(original, "ms", Point(150, 20), 1, 2,
Scalar(255, 255, 255), 2, 8, 0);
// draw results
namedWindow("prew", WINDOW_AUTOSIZE);
imshow("prew", original);
// make video output
outputVideo << original;
int key1 = waitKey(20);
}
}
}
int main(int argc, char** argv)
{
det();
return 0;
}
where is cascade25.xml ?
nice post Thx เกมออฟไลน์