feat: 切换后端至PaddleOCR-NCNN,切换工程为CMake

1.项目后端整体迁移至PaddleOCR-NCNN算法,已通过基本的兼容性测试
2.工程改为使用CMake组织,后续为了更好地兼容第三方库,不再提供QMake工程
3.重整权利声明文件,重整代码工程,确保最小化侵权风险

Log: 切换后端至PaddleOCR-NCNN,切换工程为CMake
Change-Id: I4d5d2c5d37505a4a24b389b1a4c5d12f17bfa38c
This commit is contained in:
wangzhengyang
2022-05-10 09:54:44 +08:00
parent ecdd171c6f
commit 718c41634f
10018 changed files with 3593797 additions and 186748 deletions

View File

@ -0,0 +1,26 @@
ocv_install_example_src(tapi *.cpp *.hpp CMakeLists.txt)
set(OPENCV_TAPI_SAMPLES_REQUIRED_DEPS
opencv_core
opencv_imgproc
opencv_video
opencv_imgcodecs
opencv_videoio
opencv_highgui
opencv_objdetect
opencv_features2d
opencv_calib3d
opencv_flann)
ocv_check_dependencies(${OPENCV_TAPI_SAMPLES_REQUIRED_DEPS})
if(NOT BUILD_EXAMPLES OR NOT OCV_DEPENDENCIES_FOUND)
return()
endif()
project(tapi_samples)
ocv_include_modules_recurse(${OPENCV_TAPI_SAMPLES_REQUIRED_DEPS})
file(GLOB all_samples RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
foreach(sample_filename ${all_samples})
ocv_define_sample(tgt ${sample_filename} tapi)
ocv_target_link_libraries(${tgt} PRIVATE ${OPENCV_LINKER_LIBS} ${OPENCV_TAPI_SAMPLES_REQUIRED_DEPS})
endforeach()

View File

@ -0,0 +1,123 @@
#include <iostream>
#include <string>
#include "opencv2/core.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/video.hpp"
using namespace std;
using namespace cv;
#define M_MOG2 2
#define M_KNN 3
int main(int argc, const char** argv)
{
CommandLineParser cmd(argc, argv,
"{ c camera | | use camera }"
"{ f file | ../data/vtest.avi | input video file }"
"{ t type | mog2 | method's type (knn, mog2) }"
"{ h help | | print help message }"
"{ m cpu_mode | false | press 'm' to switch OpenCL<->CPU}");
if (cmd.has("help"))
{
cout << "Usage : bgfg_segm [options]" << endl;
cout << "Available options:" << endl;
cmd.printMessage();
return EXIT_SUCCESS;
}
bool useCamera = cmd.has("camera");
string file = cmd.get<string>("file");
string method = cmd.get<string>("type");
if (method != "mog" && method != "mog2")
{
cerr << "Incorrect method" << endl;
return EXIT_FAILURE;
}
int m = method == "mog2" ? M_MOG2 : M_KNN;
VideoCapture cap;
if (useCamera)
cap.open(0);
else
cap.open(file);
if (!cap.isOpened())
{
cout << "can not open camera or video file" << endl;
return EXIT_FAILURE;
}
UMat frame, fgmask, fgimg;
cap >> frame;
fgimg.create(frame.size(), frame.type());
Ptr<BackgroundSubtractorKNN> knn = createBackgroundSubtractorKNN();
Ptr<BackgroundSubtractorMOG2> mog2 = createBackgroundSubtractorMOG2();
switch (m)
{
case M_KNN:
knn->apply(frame, fgmask);
break;
case M_MOG2:
mog2->apply(frame, fgmask);
break;
}
bool running=true;
for (;;)
{
if(!running)
break;
cap >> frame;
if (frame.empty())
break;
int64 start = getTickCount();
//update the model
switch (m)
{
case M_KNN:
knn->apply(frame, fgmask);
break;
case M_MOG2:
mog2->apply(frame, fgmask);
break;
}
double fps = getTickFrequency() / (getTickCount() - start);
std::cout << "FPS : " << fps << std::endl;
std::cout << fgimg.size() << std::endl;
fgimg.setTo(Scalar::all(0));
frame.copyTo(fgimg, fgmask);
imshow("image", frame);
imshow("foreground mask", fgmask);
imshow("foreground image", fgimg);
char key = (char)waitKey(30);
switch (key)
{
case 27:
running = false;
break;
case 'm':
case 'M':
ocl::setUseOpenCL(!ocl::useOpenCL());
cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL enabled" : "CPU") << " mode\n";
break;
}
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,227 @@
#include "opencv2/core/utility.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
#include <cctype>
static cv::UMat image;
static bool backprojMode = false;
static bool selectObject = false;
static int trackObject = 0;
static bool showHist = true;
static cv::Rect selection;
static int vmin = 10, vmax = 256, smin = 30;
static void onMouse(int event, int x, int y, int, void*)
{
static cv::Point origin;
if (selectObject)
{
selection.x = std::min(x, origin.x);
selection.y = std::min(y, origin.y);
selection.width = std::abs(x - origin.x);
selection.height = std::abs(y - origin.y);
selection &= cv::Rect(0, 0, image.cols, image.rows);
}
switch (event)
{
case cv::EVENT_LBUTTONDOWN:
origin = cv::Point(x, y);
selection = cv::Rect(x, y, 0, 0);
selectObject = true;
break;
case cv::EVENT_LBUTTONUP:
selectObject = false;
if (selection.width > 0 && selection.height > 0)
trackObject = -1;
break;
default:
break;
}
}
static void help()
{
std::cout << "\nThis is a demo that shows mean-shift based tracking using Transparent API\n"
"You select a color objects such as your face and it tracks it.\n"
"This reads from video camera (0 by default, or the camera number the user enters\n"
"Usage: \n"
" ./camshiftdemo [camera number]\n";
std::cout << "\n\nHot keys: \n"
"\tESC - quit the program\n"
"\ts - stop the tracking\n"
"\tb - switch to/from backprojection view\n"
"\th - show/hide object histogram\n"
"\tp - pause video\n"
"\tc - use OpenCL or not\n"
"To initialize tracking, select the object with mouse\n";
}
int main(int argc, const char ** argv)
{
help();
cv::VideoCapture cap;
cv::Rect trackWindow;
int hsize = 16;
float hranges[2] = { 0, 180 };
const char * const keys = { "{@camera_number| 0 | camera number}" };
cv::CommandLineParser parser(argc, argv, keys);
int camNum = parser.get<int>(0);
cap.open(camNum);
if (!cap.isOpened())
{
help();
std::cout << "***Could not initialize capturing...***\n";
std::cout << "Current parameter's value: \n";
parser.printMessage();
return EXIT_FAILURE;
}
cv::namedWindow("Histogram", cv::WINDOW_NORMAL);
cv::namedWindow("CamShift Demo", cv::WINDOW_NORMAL);
cv::setMouseCallback("CamShift Demo", onMouse);
cv::createTrackbar("Vmin", "CamShift Demo", &vmin, 256);
cv::createTrackbar("Vmax", "CamShift Demo", &vmax, 256);
cv::createTrackbar("Smin", "CamShift Demo", &smin, 256);
cv::Mat frame, histimg(200, 320, CV_8UC3, cv::Scalar::all(0));
cv::UMat hsv, hist, hue, mask, backproj;
bool paused = false;
for ( ; ; )
{
if (!paused)
{
cap >> frame;
if (frame.empty())
break;
}
frame.copyTo(image);
if (!paused)
{
cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV);
if (trackObject)
{
int _vmin = vmin, _vmax = vmax;
cv::inRange(hsv, cv::Scalar(0, smin, std::min(_vmin, _vmax)),
cv::Scalar(180, 256, std::max(_vmin, _vmax)), mask);
int fromTo[2] = { 0,0 };
hue.create(hsv.size(), hsv.depth());
cv::mixChannels(std::vector<cv::UMat>(1, hsv), std::vector<cv::UMat>(1, hue), fromTo, 1);
if (trackObject < 0)
{
cv::UMat roi(hue, selection), maskroi(mask, selection);
cv::calcHist(std::vector<cv::Mat>(1, roi.getMat(cv::ACCESS_READ)), std::vector<int>(1, 0),
maskroi, hist, std::vector<int>(1, hsize), std::vector<float>(hranges, hranges + 2));
cv::normalize(hist, hist, 0, 255, cv::NORM_MINMAX);
trackWindow = selection;
trackObject = 1;
histimg = cv::Scalar::all(0);
int binW = histimg.cols / hsize;
cv::Mat buf (1, hsize, CV_8UC3);
for (int i = 0; i < hsize; i++)
buf.at<cv::Vec3b>(i) = cv::Vec3b(cv::saturate_cast<uchar>(i*180./hsize), 255, 255);
cv::cvtColor(buf, buf, cv::COLOR_HSV2BGR);
{
cv::Mat _hist = hist.getMat(cv::ACCESS_READ);
for (int i = 0; i < hsize; i++)
{
int val = cv::saturate_cast<int>(_hist.at<float>(i)*histimg.rows/255);
cv::rectangle(histimg, cv::Point(i*binW, histimg.rows),
cv::Point((i+1)*binW, histimg.rows - val),
cv::Scalar(buf.at<cv::Vec3b>(i)), -1, 8);
}
}
}
cv::calcBackProject(std::vector<cv::UMat>(1, hue), std::vector<int>(1, 0), hist, backproj,
std::vector<float>(hranges, hranges + 2), 1.0);
cv::bitwise_and(backproj, mask, backproj);
cv::RotatedRect trackBox = cv::CamShift(backproj, trackWindow,
cv::TermCriteria(cv::TermCriteria::EPS | cv::TermCriteria::COUNT, 10, 1));
if (trackWindow.area() <= 1)
{
int cols = backproj.cols, rows = backproj.rows, r = (std::min(cols, rows) + 5)/6;
trackWindow = cv::Rect(trackWindow.x - r, trackWindow.y - r,
trackWindow.x + r, trackWindow.y + r) &
cv::Rect(0, 0, cols, rows);
}
if (backprojMode)
cv::cvtColor(backproj, image, cv::COLOR_GRAY2BGR);
{
cv::Mat _image = image.getMat(cv::ACCESS_RW);
cv::ellipse(_image, trackBox, cv::Scalar(0, 0, 255), 3, cv::LINE_AA);
}
}
}
else if (trackObject < 0)
paused = false;
if (selectObject && selection.width > 0 && selection.height > 0)
{
cv::UMat roi(image, selection);
cv::bitwise_not(roi, roi);
}
cv::imshow("CamShift Demo", image);
if (showHist)
cv::imshow("Histogram", histimg);
char c = (char)cv::waitKey(10);
if (c == 27)
break;
switch(c)
{
case 'b':
backprojMode = !backprojMode;
break;
case 't':
trackObject = 0;
histimg = cv::Scalar::all(0);
break;
case 'h':
showHist = !showHist;
if (!showHist)
cv::destroyWindow("Histogram");
else
cv::namedWindow("Histogram", cv::WINDOW_AUTOSIZE);
break;
case 'p':
paused = !paused;
break;
case 'c':
cv::ocl::setUseOpenCL(!cv::ocl::useOpenCL());
default:
break;
}
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,113 @@
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
using namespace std;
Ptr<CLAHE> pFilter;
int tilesize;
int cliplimit;
static void TSize_Callback(int pos, void* /*data*/)
{
if(pos==0)
pFilter->setTilesGridSize(Size(1,1));
else
pFilter->setTilesGridSize(Size(tilesize,tilesize));
}
static void Clip_Callback(int, void* /*data*/)
{
pFilter->setClipLimit(cliplimit);
}
int main(int argc, char** argv)
{
const char* keys =
"{ i input | | specify input image }"
"{ c camera | 0 | specify camera id }"
"{ o output | clahe_output.jpg | specify output save path}"
"{ h help | | print help message }";
cv::CommandLineParser cmd(argc, argv, keys);
if (cmd.has("help"))
{
cout << "Usage : clahe [options]" << endl;
cout << "Available options:" << endl;
cmd.printMessage();
return EXIT_SUCCESS;
}
string infile = cmd.get<string>("i"), outfile = cmd.get<string>("o");
int camid = cmd.get<int>("c");
VideoCapture capture;
namedWindow("CLAHE");
createTrackbar("Tile Size", "CLAHE", &tilesize, 32, (TrackbarCallback)TSize_Callback);
createTrackbar("Clip Limit", "CLAHE", &cliplimit, 20, (TrackbarCallback)Clip_Callback);
UMat frame, outframe;
int cur_clip;
Size cur_tilesize;
pFilter = createCLAHE();
cur_clip = (int)pFilter->getClipLimit();
cur_tilesize = pFilter->getTilesGridSize();
setTrackbarPos("Tile Size", "CLAHE", cur_tilesize.width);
setTrackbarPos("Clip Limit", "CLAHE", cur_clip);
if(!infile.empty())
{
infile = samples::findFile(infile);
imread(infile).copyTo(frame);
if(frame.empty())
{
cout << "error read image: " << infile << endl;
return EXIT_FAILURE;
}
}
else
capture.open(camid);
cout << "\nControls:\n"
<< "\to - save output image\n"
<< "\tm - switch OpenCL <-> CPU mode"
<< "\tESC - exit\n";
for (;;)
{
if(capture.isOpened())
capture.read(frame);
else
imread(infile).copyTo(frame);
if(frame.empty())
{
waitKey();
break;
}
cvtColor(frame, frame, COLOR_BGR2GRAY);
pFilter->apply(frame, outframe);
imshow("CLAHE", outframe);
char key = (char)waitKey(3);
if(key == 'o')
imwrite(outfile, outframe);
else if(key == 27)
break;
else if(key == 'm')
{
ocl::setUseOpenCL(!cv::ocl::useOpenCL());
cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL enabled" : "CPU") << " mode\n";
}
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,151 @@
// 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 <iostream>
#include <iomanip>
#include <vector>
#include "opencv2/core/ocl.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/video.hpp"
using namespace std;
using namespace cv;
static Mat getVisibleFlow(InputArray flow)
{
vector<UMat> flow_vec;
split(flow, flow_vec);
UMat magnitude, angle;
cartToPolar(flow_vec[0], flow_vec[1], magnitude, angle, true);
magnitude.convertTo(magnitude, CV_32F, 0.2);
vector<UMat> hsv_vec;
hsv_vec.push_back(angle);
hsv_vec.push_back(UMat::ones(angle.size(), angle.type()));
hsv_vec.push_back(magnitude);
UMat hsv;
merge(hsv_vec, hsv);
Mat img;
cvtColor(hsv, img, COLOR_HSV2BGR);
return img;
}
static Size fitSize(const Size & sz, const Size & bounds)
{
CV_Assert(!sz.empty());
if (sz.width > bounds.width || sz.height > bounds.height)
{
double scale = std::min((double)bounds.width / sz.width, (double)bounds.height / sz.height);
return Size(cvRound(sz.width * scale), cvRound(sz.height * scale));
}
return sz;
}
int main(int argc, const char* argv[])
{
const char* keys =
"{ h help | | print help message }"
"{ c camera | 0 | capture video from camera (device index starting from 0) }"
"{ a algorithm | fb | algorithm (supported: 'fb', 'dis')}"
"{ m cpu | | run without OpenCL }"
"{ v video | | use video as input }"
"{ o original | | use original frame size (do not resize to 640x480)}"
;
CommandLineParser parser(argc, argv, keys);
parser.about("This sample demonstrates using of dense optical flow algorithms.");
if (parser.has("help"))
{
parser.printMessage();
return 0;
}
int camera = parser.get<int>("camera");
string algorithm = parser.get<string>("algorithm");
bool useCPU = parser.has("cpu");
string filename = parser.get<string>("video");
bool useOriginalSize = parser.has("original");
if (!parser.check())
{
parser.printErrors();
return 1;
}
VideoCapture cap;
if(filename.empty())
cap.open(camera);
else
cap.open(filename);
if (!cap.isOpened())
{
cout << "Can not open video stream: '" << (filename.empty() ? "<camera>" : filename) << "'" << endl;
return 2;
}
Ptr<DenseOpticalFlow> alg;
if (algorithm == "fb")
alg = FarnebackOpticalFlow::create();
else if (algorithm == "dis")
alg = DISOpticalFlow::create(DISOpticalFlow::PRESET_FAST);
else
{
cout << "Invalid algorithm: " << algorithm << endl;
return 3;
}
ocl::setUseOpenCL(!useCPU);
cout << "Press 'm' to toggle CPU/GPU processing mode" << endl;
cout << "Press ESC or 'q' to exit" << endl;
UMat prevFrame, frame, input_frame, flow;
for(;;)
{
if (!cap.read(input_frame) || input_frame.empty())
{
cout << "Finished reading: empty frame" << endl;
break;
}
Size small_size = fitSize(input_frame.size(), Size(640, 480));
if (!useOriginalSize && small_size != input_frame.size())
resize(input_frame, frame, small_size);
else
frame = input_frame;
cvtColor(frame, frame, COLOR_BGR2GRAY);
imshow("frame", frame);
if (!prevFrame.empty())
{
int64 t = getTickCount();
alg->calc(prevFrame, frame, flow);
t = getTickCount() - t;
{
Mat img = getVisibleFlow(flow);
ostringstream buf;
buf << "Algo: " << algorithm << " | "
<< "Mode: " << (useCPU ? "CPU" : "GPU") << " | "
<< "FPS: " << fixed << setprecision(1) << (getTickFrequency() / (double)t);
putText(img, buf.str(), Point(10, 30), FONT_HERSHEY_PLAIN, 2.0, Scalar(0, 0, 255), 2, LINE_AA);
imshow("Dense optical flow field", img);
}
}
frame.copyTo(prevFrame);
// interact with user
const char key = (char)waitKey(30);
if (key == 27 || key == 'q') // ESC
{
cout << "Exit requested" << endl;
break;
}
else if (key == 'm')
{
useCPU = !useCPU;
ocl::setUseOpenCL(!useCPU);
cout << "Set processing mode to: " << (useCPU ? "CPU" : "GPU") << endl;
}
}
return 0;
}

View File

@ -0,0 +1,352 @@
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>
#include <stdexcept>
#include <opencv2/core/ocl.hpp>
#include <opencv2/core/utility.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
class App
{
public:
App(CommandLineParser& cmd);
void run();
void handleKey(char key);
void hogWorkBegin();
void hogWorkEnd();
string hogWorkFps() const;
void workBegin();
void workEnd();
string workFps() const;
private:
App operator=(App&);
//Args args;
bool running;
bool make_gray;
double scale;
double resize_scale;
int win_width;
int win_stride_width, win_stride_height;
int gr_threshold;
int nlevels;
double hit_threshold;
bool gamma_corr;
int64 hog_work_begin;
double hog_work_fps;
int64 work_begin;
double work_fps;
string img_source;
string vdo_source;
string output;
int camera_id;
bool write_once;
};
int main(int argc, char** argv)
{
const char* keys =
"{ h help | | print help message }"
"{ i input | | specify input image}"
"{ c camera | -1 | enable camera capturing }"
"{ v video | vtest.avi | use video as input }"
"{ g gray | | convert image to gray one or not}"
"{ s scale | 1.0 | resize the image before detect}"
"{ o output | output.avi | specify output path when input is images}";
CommandLineParser cmd(argc, argv, keys);
if (cmd.has("help"))
{
cmd.printMessage();
return EXIT_SUCCESS;
}
App app(cmd);
try
{
app.run();
}
catch (const Exception& e)
{
return cout << "error: " << e.what() << endl, 1;
}
catch (const exception& e)
{
return cout << "error: " << e.what() << endl, 1;
}
catch(...)
{
return cout << "unknown exception" << endl, 1;
}
return EXIT_SUCCESS;
}
App::App(CommandLineParser& cmd)
{
cout << "\nControls:\n"
<< "\tESC - exit\n"
<< "\tm - change mode GPU <-> CPU\n"
<< "\tg - convert image to gray or not\n"
<< "\to - save output image once, or switch on/off video save\n"
<< "\t1/q - increase/decrease HOG scale\n"
<< "\t2/w - increase/decrease levels count\n"
<< "\t3/e - increase/decrease HOG group threshold\n"
<< "\t4/r - increase/decrease hit threshold\n"
<< endl;
make_gray = cmd.has("gray");
resize_scale = cmd.get<double>("s");
vdo_source = samples::findFileOrKeep(cmd.get<string>("v"));
img_source = cmd.get<string>("i");
output = cmd.get<string>("o");
camera_id = cmd.get<int>("c");
win_width = 48;
win_stride_width = 8;
win_stride_height = 8;
gr_threshold = 8;
nlevels = 13;
hit_threshold = 1.4;
scale = 1.05;
gamma_corr = true;
write_once = false;
cout << "Group threshold: " << gr_threshold << endl;
cout << "Levels number: " << nlevels << endl;
cout << "Win width: " << win_width << endl;
cout << "Win stride: (" << win_stride_width << ", " << win_stride_height << ")\n";
cout << "Hit threshold: " << hit_threshold << endl;
cout << "Gamma correction: " << gamma_corr << endl;
cout << endl;
}
void App::run()
{
running = true;
VideoWriter video_writer;
Size win_size(win_width, win_width * 2);
Size win_stride(win_stride_width, win_stride_height);
// Create HOG descriptors and detectors here
HOGDescriptor hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9, 1, -1,
HOGDescriptor::L2Hys, 0.2, gamma_corr, cv::HOGDescriptor::DEFAULT_NLEVELS);
hog.setSVMDetector( HOGDescriptor::getDaimlerPeopleDetector() );
while (running)
{
VideoCapture vc;
UMat frame;
if (vdo_source!="")
{
vc.open(vdo_source.c_str());
if (!vc.isOpened())
throw runtime_error(string("can't open video file: " + vdo_source));
vc >> frame;
}
else if (camera_id != -1)
{
vc.open(camera_id);
if (!vc.isOpened())
{
stringstream msg;
msg << "can't open camera: " << camera_id;
throw runtime_error(msg.str());
}
vc >> frame;
}
else
{
imread(img_source).copyTo(frame);
if (frame.empty())
throw runtime_error(string("can't open image file: " + img_source));
}
UMat img_aux, img, img_to_show;
// Iterate over all frames
while (running && !frame.empty())
{
workBegin();
// Change format of the image
if (make_gray) cvtColor(frame, img_aux, COLOR_BGR2GRAY );
else frame.copyTo(img_aux);
// Resize image
if (abs(scale-1.0)>0.001)
{
Size sz((int)((double)img_aux.cols/resize_scale), (int)((double)img_aux.rows/resize_scale));
resize(img_aux, img, sz, 0, 0, INTER_LINEAR_EXACT);
}
else img = img_aux;
img.copyTo(img_to_show);
hog.nlevels = nlevels;
vector<Rect> found;
// Perform HOG classification
hogWorkBegin();
hog.detectMultiScale(img, found, hit_threshold, win_stride,
Size(0, 0), scale, gr_threshold);
hogWorkEnd();
// Draw positive classified windows
for (size_t i = 0; i < found.size(); i++)
{
rectangle(img_to_show, found[i], Scalar(0, 255, 0), 3);
}
putText(img_to_show, ocl::useOpenCL() ? "Mode: OpenCL" : "Mode: CPU", Point(5, 25), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2);
putText(img_to_show, "FPS (HOG only): " + hogWorkFps(), Point(5, 65), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2);
putText(img_to_show, "FPS (total): " + workFps(), Point(5, 105), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2);
imshow("opencv_hog", img_to_show);
if (vdo_source!="" || camera_id!=-1) vc >> frame;
workEnd();
if (output!="" && write_once)
{
if (img_source!="") // write image
{
write_once = false;
imwrite(output, img_to_show);
}
else //write video
{
if (!video_writer.isOpened())
{
video_writer.open(output, VideoWriter::fourcc('x','v','i','d'), 24,
img_to_show.size(), true);
if (!video_writer.isOpened())
throw std::runtime_error("can't create video writer");
}
if (make_gray) cvtColor(img_to_show, img, COLOR_GRAY2BGR);
else cvtColor(img_to_show, img, COLOR_BGRA2BGR);
video_writer << img;
}
}
handleKey((char)waitKey(3));
}
}
}
void App::handleKey(char key)
{
switch (key)
{
case 27:
running = false;
break;
case 'm':
case 'M':
ocl::setUseOpenCL(!cv::ocl::useOpenCL());
cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL enabled" : "CPU") << " mode\n";
break;
case 'g':
case 'G':
make_gray = !make_gray;
cout << "Convert image to gray: " << (make_gray ? "YES" : "NO") << endl;
break;
case '1':
scale *= 1.05;
cout << "Scale: " << scale << endl;
break;
case 'q':
case 'Q':
scale /= 1.05;
cout << "Scale: " << scale << endl;
break;
case '2':
nlevels++;
cout << "Levels number: " << nlevels << endl;
break;
case 'w':
case 'W':
nlevels = max(nlevels - 1, 1);
cout << "Levels number: " << nlevels << endl;
break;
case '3':
gr_threshold++;
cout << "Group threshold: " << gr_threshold << endl;
break;
case 'e':
case 'E':
gr_threshold = max(0, gr_threshold - 1);
cout << "Group threshold: " << gr_threshold << endl;
break;
case '4':
hit_threshold+=0.25;
cout << "Hit threshold: " << hit_threshold << endl;
break;
case 'r':
case 'R':
hit_threshold = max(0.0, hit_threshold - 0.25);
cout << "Hit threshold: " << hit_threshold << endl;
break;
case 'c':
case 'C':
gamma_corr = !gamma_corr;
cout << "Gamma correction: " << gamma_corr << endl;
break;
case 'o':
case 'O':
write_once = !write_once;
break;
}
}
inline void App::hogWorkBegin()
{
hog_work_begin = getTickCount();
}
inline void App::hogWorkEnd()
{
int64 delta = getTickCount() - hog_work_begin;
double freq = getTickFrequency();
hog_work_fps = freq / delta;
}
inline string App::hogWorkFps() const
{
stringstream ss;
ss << hog_work_fps;
return ss.str();
}
inline void App::workBegin()
{
work_begin = getTickCount();
}
inline void App::workEnd()
{
int64 delta = getTickCount() - work_begin;
double freq = getTickFrequency();
work_fps = freq / delta;
}
inline string App::workFps() const
{
stringstream ss;
ss << work_fps;
return ss.str();
}

View File

@ -0,0 +1,164 @@
// 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/core.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
static const char* opencl_kernel_src =
"__kernel void magnutude_filter_8u(\n"
" __global const uchar* src, int src_step, int src_offset,\n"
" __global uchar* dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,\n"
" float scale)\n"
"{\n"
" int x = get_global_id(0);\n"
" int y = get_global_id(1);\n"
" if (x < dst_cols && y < dst_rows)\n"
" {\n"
" int dst_idx = y * dst_step + x + dst_offset;\n"
" if (x > 0 && x < dst_cols - 1 && y > 0 && y < dst_rows - 2)\n"
" {\n"
" int src_idx = y * src_step + x + src_offset;\n"
" int dx = (int)src[src_idx]*2 - src[src_idx - 1] - src[src_idx + 1];\n"
" int dy = (int)src[src_idx]*2 - src[src_idx - 1*src_step] - src[src_idx + 1*src_step];\n"
" dst[dst_idx] = convert_uchar_sat(sqrt((float)(dx*dx + dy*dy)) * scale);\n"
" }\n"
" else\n"
" {\n"
" dst[dst_idx] = 0;\n"
" }\n"
" }\n"
"}\n";
int main(int argc, char** argv)
{
const char* keys =
"{ i input | | specify input image }"
"{ h help | | print help message }";
cv::CommandLineParser args(argc, argv, keys);
if (args.has("help"))
{
cout << "Usage : " << argv[0] << " [options]" << endl;
cout << "Available options:" << endl;
args.printMessage();
return EXIT_SUCCESS;
}
cv::ocl::Context ctx = cv::ocl::Context::getDefault();
if (!ctx.ptr())
{
cerr << "OpenCL is not available" << endl;
return 1;
}
cv::ocl::Device device = cv::ocl::Device::getDefault();
if (!device.compilerAvailable())
{
cerr << "OpenCL compiler is not available" << endl;
return 1;
}
UMat src;
{
string image_file = args.get<string>("i");
if (!image_file.empty())
{
Mat image = imread(samples::findFile(image_file));
if (image.empty())
{
cout << "error read image: " << image_file << endl;
return 1;
}
cvtColor(image, src, COLOR_BGR2GRAY);
}
else
{
Mat frame(cv::Size(640, 480), CV_8U, Scalar::all(128));
Point p(frame.cols / 2, frame.rows / 2);
line(frame, Point(0, frame.rows / 2), Point(frame.cols, frame.rows / 2), 1);
circle(frame, p, 200, Scalar(32, 32, 32), 8, LINE_AA);
string str = "OpenCL";
int baseLine = 0;
Size box = getTextSize(str, FONT_HERSHEY_COMPLEX, 2, 5, &baseLine);
putText(frame, str, Point((frame.cols - box.width) / 2, (frame.rows - box.height) / 2 + baseLine),
FONT_HERSHEY_COMPLEX, 2, Scalar(255, 255, 255), 5, LINE_AA);
frame.copyTo(src);
}
}
cv::String module_name; // empty to disable OpenCL cache
{
cout << "OpenCL program source: " << endl;
cout << "======================================================================================================" << endl;
cout << opencl_kernel_src << endl;
cout << "======================================================================================================" << endl;
//! [Define OpenCL program source]
cv::ocl::ProgramSource source(module_name, "simple", opencl_kernel_src, "");
//! [Define OpenCL program source]
//! [Compile/build OpenCL for current OpenCL device]
cv::String errmsg;
cv::ocl::Program program(source, "", errmsg);
if (program.ptr() == NULL)
{
cerr << "Can't compile OpenCL program:" << endl << errmsg << endl;
return 1;
}
//! [Compile/build OpenCL for current OpenCL device]
if (!errmsg.empty())
{
cout << "OpenCL program build log:" << endl << errmsg << endl;
}
//! [Get OpenCL kernel by name]
cv::ocl::Kernel k("magnutude_filter_8u", program);
if (k.empty())
{
cerr << "Can't get OpenCL kernel" << endl;
return 1;
}
//! [Get OpenCL kernel by name]
UMat result(src.size(), CV_8UC1);
//! [Define kernel parameters and run]
size_t globalSize[2] = {(size_t)src.cols, (size_t)src.rows};
size_t localSize[2] = {8, 8};
bool executionResult = k
.args(
cv::ocl::KernelArg::ReadOnlyNoSize(src), // size is not used (similar to 'dst' size)
cv::ocl::KernelArg::WriteOnly(result),
(float)2.0
)
.run(2, globalSize, localSize, true);
if (!executionResult)
{
cerr << "OpenCL kernel launch failed" << endl;
return 1;
}
//! [Define kernel parameters and run]
imshow("Source", src);
imshow("Result", result);
for (;;)
{
int key = waitKey();
if (key == 27/*ESC*/ || key == 'q' || key == 'Q')
break;
}
}
return 0;
}

View File

@ -0,0 +1,232 @@
#include <iostream>
#include <vector>
#include <iomanip>
#include "opencv2/core/utility.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/video/video.hpp"
using namespace std;
using namespace cv;
typedef unsigned char uchar;
#define LOOP_NUM 10
int64 work_begin = 0;
int64 work_end = 0;
static void workBegin()
{
work_begin = getTickCount();
}
static void workEnd()
{
work_end += (getTickCount() - work_begin);
}
static double getTime()
{
return work_end * 1000. / getTickFrequency();
}
static void drawArrows(UMat& _frame, const vector<Point2f>& prevPts, const vector<Point2f>& nextPts, const vector<uchar>& status,
Scalar line_color = Scalar(0, 0, 255))
{
Mat frame = _frame.getMat(ACCESS_WRITE);
for (size_t i = 0; i < prevPts.size(); ++i)
{
if (status[i])
{
int line_thickness = 1;
Point p = prevPts[i];
Point q = nextPts[i];
double angle = atan2((double) p.y - q.y, (double) p.x - q.x);
double hypotenuse = sqrt( (double)(p.y - q.y)*(p.y - q.y) + (double)(p.x - q.x)*(p.x - q.x) );
if (hypotenuse < 1.0)
continue;
// Here we lengthen the arrow by a factor of three.
q.x = (int) (p.x - 3 * hypotenuse * cos(angle));
q.y = (int) (p.y - 3 * hypotenuse * sin(angle));
// Now we draw the main line of the arrow.
line(frame, p, q, line_color, line_thickness);
// Now draw the tips of the arrow. I do some scaling so that the
// tips look proportional to the main line of the arrow.
p.x = (int) (q.x + 9 * cos(angle + CV_PI / 4));
p.y = (int) (q.y + 9 * sin(angle + CV_PI / 4));
line(frame, p, q, line_color, line_thickness);
p.x = (int) (q.x + 9 * cos(angle - CV_PI / 4));
p.y = (int) (q.y + 9 * sin(angle - CV_PI / 4));
line(frame, p, q, line_color, line_thickness);
}
}
}
int main(int argc, const char* argv[])
{
const char* keys =
"{ h help | | print help message }"
"{ l left | | specify left image }"
"{ r right | | specify right image }"
"{ c camera | 0 | enable camera capturing }"
"{ v video | | use video as input }"
"{ o output | pyrlk_output.jpg| specify output save path when input is images }"
"{ points | 1000 | specify points count [GoodFeatureToTrack] }"
"{ min_dist | 0 | specify minimal distance between points [GoodFeatureToTrack] }"
"{ m cpu_mode | false | run without OpenCL }";
CommandLineParser cmd(argc, argv, keys);
if (cmd.has("help"))
{
cout << "Usage: pyrlk_optical_flow [options]" << endl;
cout << "Available options:" << endl;
cmd.printMessage();
return EXIT_SUCCESS;
}
bool defaultPicturesFail = true;
string fname0 = samples::findFile(cmd.get<string>("left"));
string fname1 = samples::findFile(cmd.get<string>("right"));
string vdofile = cmd.get<string>("video");
string outfile = cmd.get<string>("output");
int points = cmd.get<int>("points");
double minDist = cmd.get<double>("min_dist");
int inputName = cmd.get<int>("c");
UMat frame0;
imread(fname0, IMREAD_GRAYSCALE).copyTo(frame0);
UMat frame1;
imread(fname1, IMREAD_GRAYSCALE).copyTo(frame1);
vector<cv::Point2f> pts(points);
vector<cv::Point2f> nextPts(points);
vector<unsigned char> status(points);
vector<float> err;
cout << "Points count : " << points << endl << endl;
if (frame0.empty() || frame1.empty())
{
VideoCapture capture;
UMat frame, frameCopy;
UMat frame0Gray, frame1Gray;
UMat ptr0, ptr1;
if(vdofile.empty())
capture.open( inputName );
else
capture.open(vdofile.c_str());
int c = inputName ;
if(!capture.isOpened())
{
if(vdofile.empty())
cout << "Capture from CAM " << c << " didn't work" << endl;
else
cout << "Capture from file " << vdofile << " failed" <<endl;
if (defaultPicturesFail)
return EXIT_FAILURE;
goto nocamera;
}
cout << "In capture ..." << endl;
for(int i = 0;; i++)
{
if( !capture.read(frame) )
break;
if (i == 0)
{
frame.copyTo( frame0 );
cvtColor(frame0, frame0Gray, COLOR_BGR2GRAY);
}
else
{
if (i%2 == 1)
{
frame.copyTo(frame1);
cvtColor(frame1, frame1Gray, COLOR_BGR2GRAY);
ptr0 = frame0Gray;
ptr1 = frame1Gray;
}
else
{
frame.copyTo(frame0);
cvtColor(frame0, frame0Gray, COLOR_BGR2GRAY);
ptr0 = frame1Gray;
ptr1 = frame0Gray;
}
pts.clear();
goodFeaturesToTrack(ptr0, pts, points, 0.01, 0.0);
if(pts.size() == 0)
continue;
calcOpticalFlowPyrLK(ptr0, ptr1, pts, nextPts, status, err);
if (i%2 == 1)
frame1.copyTo(frameCopy);
else
frame0.copyTo(frameCopy);
drawArrows(frameCopy, pts, nextPts, status, Scalar(255, 0, 0));
imshow("PyrLK [Sparse]", frameCopy);
}
char key = (char)waitKey(10);
if (key == 27)
break;
else if (key == 'm' || key == 'M')
{
ocl::setUseOpenCL(!cv::ocl::useOpenCL());
cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n";
}
}
capture.release();
}
else
{
nocamera:
if (cmd.has("cpu_mode"))
{
ocl::setUseOpenCL(false);
std::cout << "OpenCL was disabled" << std::endl;
}
for(int i = 0; i <= LOOP_NUM; i ++)
{
cout << "loop" << i << endl;
if (i > 0) workBegin();
goodFeaturesToTrack(frame0, pts, points, 0.01, minDist);
calcOpticalFlowPyrLK(frame0, frame1, pts, nextPts, status, err);
if (i > 0 && i <= LOOP_NUM)
workEnd();
if (i == LOOP_NUM)
{
cout << "average time (noCamera) : ";
cout << getTime() / LOOP_NUM << " ms" << endl;
drawArrows(frame0, pts, nextPts, status, Scalar(255, 0, 0));
imshow("PyrLK [Sparse]", frame0);
imwrite(outfile, frame0);
}
}
}
waitKey();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,200 @@
#include "opencv2/core.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int thresh = 50, N = 11;
const char* wndname = "Square Detection Demo";
// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2
static double angle( Point pt1, Point pt2, Point pt0 )
{
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}
// returns sequence of squares detected on the image.
static void findSquares( const UMat& image, vector<vector<Point> >& squares )
{
squares.clear();
UMat pyr, timg, gray0(image.size(), CV_8U), gray;
// down-scale and upscale the image to filter out the noise
pyrDown(image, pyr, Size(image.cols/2, image.rows/2));
pyrUp(pyr, timg, image.size());
vector<vector<Point> > contours;
// find squares in every color plane of the image
for( int c = 0; c < 3; c++ )
{
int ch[] = {c, 0};
mixChannels(timg, gray0, ch, 1);
// try several threshold levels
for( int l = 0; l < N; l++ )
{
// hack: use Canny instead of zero threshold level.
// Canny helps to catch squares with gradient shading
if( l == 0 )
{
// apply Canny. Take the upper threshold from slider
// and set the lower to 0 (which forces edges merging)
Canny(gray0, gray, 0, thresh, 5);
// dilate canny output to remove potential
// holes between edge segments
dilate(gray, gray, UMat(), Point(-1,-1));
}
else
{
// apply threshold if l!=0:
// tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
threshold(gray0, gray, (l+1)*255/N, 255, THRESH_BINARY);
}
// find contours and store them all as a list
findContours(gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
vector<Point> approx;
// test each contour
for( size_t i = 0; i < contours.size(); i++ )
{
// approximate contour with accuracy proportional
// to the contour perimeter
approxPolyDP(contours[i], approx, arcLength(contours[i], true)*0.02, true);
// square contours should have 4 vertices after approximation
// relatively large area (to filter out noisy contours)
// and be convex.
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
if( approx.size() == 4 &&
fabs(contourArea(approx)) > 1000 &&
isContourConvex(approx) )
{
double maxCosine = 0;
for( int j = 2; j < 5; j++ )
{
// find the maximum cosine of the angle between joint edges
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAX(maxCosine, cosine);
}
// if cosines of all angles are small
// (all angles are ~90 degree) then write quandrange
// vertices to resultant sequence
if( maxCosine < 0.3 )
squares.push_back(approx);
}
}
}
}
}
// the function draws all the squares in the image
static void drawSquares( UMat& _image, const vector<vector<Point> >& squares )
{
Mat image = _image.getMat(ACCESS_WRITE);
for( size_t i = 0; i < squares.size(); i++ )
{
const Point* p = &squares[i][0];
int n = (int)squares[i].size();
polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, LINE_AA);
}
}
// draw both pure-C++ and ocl square results onto a single image
static UMat drawSquaresBoth( const UMat& image,
const vector<vector<Point> >& sqs)
{
UMat imgToShow(Size(image.cols, image.rows), image.type());
image.copyTo(imgToShow);
drawSquares(imgToShow, sqs);
return imgToShow;
}
int main(int argc, char** argv)
{
const char* keys =
"{ i input | ../data/pic1.png | specify input image }"
"{ o output | squares_output.jpg | specify output save path}"
"{ h help | | print help message }"
"{ m cpu_mode | | run without OpenCL }";
CommandLineParser cmd(argc, argv, keys);
if(cmd.has("help"))
{
cout << "Usage : " << argv[0] << " [options]" << endl;
cout << "Available options:" << endl;
cmd.printMessage();
return EXIT_SUCCESS;
}
if (cmd.has("cpu_mode"))
{
ocl::setUseOpenCL(false);
cout << "OpenCL was disabled" << endl;
}
string inputName = samples::findFile(cmd.get<string>("i"));
string outfile = cmd.get<string>("o");
int iterations = 10;
namedWindow( wndname, WINDOW_AUTOSIZE );
vector<vector<Point> > squares;
UMat image;
imread(inputName, IMREAD_COLOR).copyTo(image);
if( image.empty() )
{
cout << "Couldn't load " << inputName << endl;
cmd.printMessage();
return EXIT_FAILURE;
}
int j = iterations;
int64 t_cpp = 0;
//warm-ups
cout << "warming up ..." << endl;
findSquares(image, squares);
do
{
int64 t_start = getTickCount();
findSquares(image, squares);
t_cpp += cv::getTickCount() - t_start;
t_start = getTickCount();
cout << "run loop: " << j << endl;
}
while(--j);
cout << "average time: " << 1000.0f * (double)t_cpp / getTickFrequency() / iterations << "ms" << endl;
UMat result = drawSquaresBoth(image, squares);
imshow(wndname, result);
imwrite(outfile, result);
waitKey(0);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,253 @@
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/core/ocl.hpp"
#include <iostream>
using namespace std;
using namespace cv;
static void help()
{
cout << "\nThis program demonstrates the cascade recognizer. Now you can use Haar or LBP features.\n"
"This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.\n"
"It's most known use is for faces.\n"
"Usage:\n"
"./ufacedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"
" [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n"
" [--scale=<image scale greater or equal to 1, try 1.3 for example>]\n"
" [--try-flip]\n"
" [filename|camera_index]\n\n"
"see facedetect.cmd for one call:\n"
"./ufacedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml\" --scale=1.3\n\n"
"During execution:\n\tHit any key to quit.\n"
"\tUsing OpenCV version " << CV_VERSION << "\n" << endl;
}
void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,
CascadeClassifier& nestedCascade,
double scale, bool tryflip );
int main( int argc, const char** argv )
{
VideoCapture capture;
UMat frame, image;
Mat canvas;
string inputName;
bool tryflip;
CascadeClassifier cascade, nestedCascade;
double scale;
cv::CommandLineParser parser(argc, argv,
"{cascade|data/haarcascades/haarcascade_frontalface_alt.xml|}"
"{nested-cascade|data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|}"
"{help h ||}{scale|1|}{try-flip||}{@filename||}"
);
if (parser.has("help"))
{
help();
return 0;
}
string cascadeName = samples::findFile(parser.get<string>("cascade"));
string nestedCascadeName = samples::findFileOrKeep(parser.get<string>("nested-cascade"));
scale = parser.get<double>("scale");
tryflip = parser.has("try-flip");
inputName = parser.get<string>("@filename");
if ( !parser.check())
{
parser.printErrors();
help();
return -1;
}
if ( !nestedCascade.load( nestedCascadeName ) )
cerr << "WARNING: Could not load classifier cascade for nested objects: " << nestedCascadeName << endl;
if( !cascade.load( cascadeName ) )
{
cerr << "ERROR: Could not load classifier cascade: " << cascadeName << endl;
help();
return -1;
}
cout << "old cascade: " << (cascade.isOldFormatCascade() ? "TRUE" : "FALSE") << endl;
if( inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1) )
{
int camera = inputName.empty() ? 0 : inputName[0] - '0';
if(!capture.open(camera))
cout << "Capture from camera #" << camera << " didn't work" << endl;
}
else
{
inputName = samples::findFileOrKeep(inputName);
imread(inputName, IMREAD_COLOR).copyTo(image);
if( image.empty() )
{
if(!capture.open( inputName ))
cout << "Could not read " << inputName << endl;
}
}
if( capture.isOpened() )
{
cout << "Video capturing has been started ..." << endl;
for(;;)
{
capture >> frame;
if( frame.empty() )
break;
detectAndDraw( frame, canvas, cascade, nestedCascade, scale, tryflip );
char c = (char)waitKey(10);
if( c == 27 || c == 'q' || c == 'Q' )
break;
}
}
else
{
cout << "Detecting face(s) in " << inputName << endl;
if( !image.empty() )
{
detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );
waitKey(0);
}
else if( !inputName.empty() )
{
/* assume it is a text file containing the
list of the image filenames to be processed - one per line */
FILE* f = fopen( inputName.c_str(), "rt" );
if( f )
{
char buf[1000+1];
while( fgets( buf, 1000, f ) )
{
int len = (int)strlen(buf);
while( len > 0 && isspace(buf[len-1]) )
len--;
buf[len] = '\0';
cout << "file " << buf << endl;
imread(samples::findFile(buf), IMREAD_COLOR).copyTo(image);
if( !image.empty() )
{
detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );
char c = (char)waitKey(0);
if( c == 27 || c == 'q' || c == 'Q' )
break;
}
else
{
cerr << "Aw snap, couldn't read image " << buf << endl;
}
}
fclose(f);
}
}
}
return 0;
}
void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,
CascadeClassifier& nestedCascade,
double scale, bool tryflip )
{
double t = 0;
vector<Rect> faces, faces2;
const static Scalar colors[] =
{
Scalar(255,0,0),
Scalar(255,128,0),
Scalar(255,255,0),
Scalar(0,255,0),
Scalar(0,128,255),
Scalar(0,255,255),
Scalar(0,0,255),
Scalar(255,0,255)
};
static UMat gray, smallImg;
t = (double)getTickCount();
cvtColor( img, gray, COLOR_BGR2GRAY );
double fx = 1 / scale;
resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR_EXACT );
equalizeHist( smallImg, smallImg );
cascade.detectMultiScale( smallImg, faces,
1.1, 3, 0
//|CASCADE_FIND_BIGGEST_OBJECT
//|CASCADE_DO_ROUGH_SEARCH
|CASCADE_SCALE_IMAGE,
Size(30, 30) );
if( tryflip )
{
flip(smallImg, smallImg, 1);
cascade.detectMultiScale( smallImg, faces2,
1.1, 2, 0
//|CASCADE_FIND_BIGGEST_OBJECT
//|CASCADE_DO_ROUGH_SEARCH
|CASCADE_SCALE_IMAGE,
Size(30, 30) );
for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); ++r )
{
faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
}
}
t = (double)getTickCount() - t;
img.copyTo(canvas);
double fps = getTickFrequency()/t;
static double avgfps = 0;
static int nframes = 0;
nframes++;
double alpha = nframes > 50 ? 0.01 : 1./nframes;
avgfps = avgfps*(1-alpha) + fps*alpha;
putText(canvas, cv::format("OpenCL: %s, fps: %.1f", ocl::useOpenCL() ? "ON" : "OFF", avgfps), Point(50, 30),
FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,0), 2);
for ( size_t i = 0; i < faces.size(); i++ )
{
Rect r = faces[i];
vector<Rect> nestedObjects;
Point center;
Scalar color = colors[i%8];
int radius;
double aspect_ratio = (double)r.width/r.height;
if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
{
center.x = cvRound((r.x + r.width*0.5)*scale);
center.y = cvRound((r.y + r.height*0.5)*scale);
radius = cvRound((r.width + r.height)*0.25*scale);
circle( canvas, center, radius, color, 3, 8, 0 );
}
else
rectangle( canvas, Point(cvRound(r.x*scale), cvRound(r.y*scale)),
Point(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),
color, 3, 8, 0);
if( nestedCascade.empty() )
continue;
UMat smallImgROI = smallImg(r);
nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
1.1, 2, 0
//|CASCADE_FIND_BIGGEST_OBJECT
//|CASCADE_DO_ROUGH_SEARCH
//|CASCADE_DO_CANNY_PRUNING
|CASCADE_SCALE_IMAGE,
Size(30, 30) );
for ( size_t j = 0; j < nestedObjects.size(); j++ )
{
Rect nr = nestedObjects[j];
center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale);
center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale);
radius = cvRound((nr.width + nr.height)*0.25*scale);
circle( canvas, center, radius, color, 3, 8, 0 );
}
}
imshow( "result", canvas );
}

View File

@ -0,0 +1,211 @@
#include <iostream>
#include <chrono>
#include "opencv2/core.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
using namespace std;
const char* keys =
"{ i input | | input video file }"
"{ o output | | output video file, or specify 'null' to measure decoding without rendering to screen}"
"{ backend | any | VideoCapture and VideoWriter backend, valid values: 'any', 'ffmpeg', 'msmf', 'gstreamer' }"
"{ accel | any | GPU Video Acceleration, valid values: 'none', 'any', 'd3d11', 'vaapi', 'mfx' }"
"{ device | -1 | Video Acceleration device (GPU) index (-1 means default device) }"
"{ out_w | | output width (resize by calling cv::resize) }"
"{ out_h | | output height (resize by calling cv::resize) }"
"{ bitwise_not| false | apply simple image processing - bitwise_not pixels by calling cv::bitwise_not }"
"{ opencl | true | use OpenCL (inside VideoCapture/VideoWriter and for image processing) }"
"{ codec | H264 | codec id (four characters string) of output file encoder }"
"{ h help | | print help message }";
struct {
cv::VideoCaptureAPIs backend;
const char* str;
} backend_strings[] = {
{ cv::CAP_ANY, "any" },
{ cv::CAP_FFMPEG, "ffmpeg" },
{ cv::CAP_MSMF, "msmf" },
{ cv::CAP_GSTREAMER, "gstreamer" },
};
struct {
VideoAccelerationType acceleration;
const char* str;
} acceleration_strings[] = {
{ VIDEO_ACCELERATION_NONE, "none" },
{ VIDEO_ACCELERATION_ANY, "any" },
{ VIDEO_ACCELERATION_D3D11, "d3d11" },
{ VIDEO_ACCELERATION_VAAPI, "vaapi" },
{ VIDEO_ACCELERATION_MFX, "mfx" },
};
class FPSCounter {
public:
FPSCounter(double _interval) : interval(_interval) {
}
~FPSCounter() {
NewFrame(true);
}
void NewFrame(bool last_frame = false) {
num_frames++;
auto now = std::chrono::high_resolution_clock::now();
if (!last_time.time_since_epoch().count()) {
last_time = now;
}
double sec = std::chrono::duration_cast<std::chrono::duration<double>>(now - last_time).count();
if (sec >= interval || last_frame) {
printf("FPS(last %.2f sec) = %.2f\n", sec, num_frames / sec);
fflush(stdout);
num_frames = 0;
last_time = now;
}
}
private:
double interval = 1;
std::chrono::time_point<std::chrono::high_resolution_clock> last_time;
int num_frames = 0;
};
int main(int argc, char** argv)
{
cv::CommandLineParser cmd(argc, argv, keys);
if (cmd.has("help"))
{
cout << "Usage : video_acceleration [options]" << endl;
cout << "Available options:" << endl;
cmd.printMessage();
return EXIT_SUCCESS;
}
string infile = cmd.get<string>("i");
string outfile = cmd.get<string>("o");
string codec = cmd.get<string>("codec");
int device = cmd.get<int>("device");
int out_w = cmd.get<int>("out_w");
int out_h = cmd.get<int>("out_h");
bool use_opencl = cmd.get<bool>("opencl");
bool bitwise_not = cmd.get<bool>("bitwise_not");
cv::VideoCaptureAPIs backend = cv::CAP_ANY;
string backend_str = cmd.get<string>("backend");
for (size_t i = 0; i < sizeof(backend_strings)/sizeof(backend_strings[0]); i++) {
if (backend_str == backend_strings[i].str) {
backend = backend_strings[i].backend;
break;
}
}
VideoAccelerationType accel = VIDEO_ACCELERATION_ANY;
string accel_str = cmd.get<string>("accel");
for (size_t i = 0; i < sizeof(acceleration_strings) / sizeof(acceleration_strings[0]); i++) {
if (accel_str == acceleration_strings[i].str) {
accel = acceleration_strings[i].acceleration;
break;
}
}
ocl::setUseOpenCL(use_opencl);
VideoCapture capture(infile, backend, {
CAP_PROP_HW_ACCELERATION, (int)accel,
CAP_PROP_HW_DEVICE, device
});
if (!capture.isOpened()) {
cerr << "Failed to open VideoCapture" << endl;
return 1;
}
cout << "VideoCapture backend = " << capture.getBackendName() << endl;
VideoAccelerationType actual_accel = static_cast<VideoAccelerationType>(static_cast<int>(capture.get(CAP_PROP_HW_ACCELERATION)));
for (size_t i = 0; i < sizeof(acceleration_strings) / sizeof(acceleration_strings[0]); i++) {
if (actual_accel == acceleration_strings[i].acceleration) {
cout << "VideoCapture acceleration = " << acceleration_strings[i].str << endl;
cout << "VideoCapture acceleration device = " << (int)capture.get(CAP_PROP_HW_DEVICE) << endl;
break;
}
}
VideoWriter writer;
if (!outfile.empty() && outfile != "null") {
const char* codec_str = codec.c_str();
int fourcc = VideoWriter::fourcc(codec_str[0], codec_str[1], codec_str[2], codec_str[3]);
double fps = capture.get(CAP_PROP_FPS);
Size frameSize = { out_w, out_h };
if (!out_w || !out_h) {
frameSize = { (int)capture.get(CAP_PROP_FRAME_WIDTH), (int)capture.get(CAP_PROP_FRAME_HEIGHT) };
}
writer = VideoWriter(outfile, backend, fourcc, fps, frameSize, {
VIDEOWRITER_PROP_HW_ACCELERATION, (int)accel,
VIDEOWRITER_PROP_HW_DEVICE, device
});
if (!writer.isOpened()) {
cerr << "Failed to open VideoWriter" << endl;
return 1;
}
cout << "VideoWriter backend = " << writer.getBackendName() << endl;
actual_accel = static_cast<VideoAccelerationType>(static_cast<int>(writer.get(VIDEOWRITER_PROP_HW_ACCELERATION)));
for (size_t i = 0; i < sizeof(acceleration_strings) / sizeof(acceleration_strings[0]); i++) {
if (actual_accel == acceleration_strings[i].acceleration) {
cout << "VideoWriter acceleration = " << acceleration_strings[i].str << endl;
cout << "VideoWriter acceleration device = " << (int)writer.get(VIDEOWRITER_PROP_HW_DEVICE) << endl;
break;
}
}
}
cout << "\nStarting frame loop. Press ESC to exit\n";
FPSCounter fps_counter(0.5); // print FPS every 0.5 seconds
UMat frame, frame2, frame3;
for (;;)
{
capture.read(frame);
if (frame.empty()) {
cout << "End of stream" << endl;
break;
}
if (out_w && out_h) {
cv::resize(frame, frame2, cv::Size(out_w, out_h));
//cv::cvtColor(frame, outframe, COLOR_BGRA2RGBA);
}
else {
frame2 = frame;
}
if (bitwise_not) {
cv::bitwise_not(frame2, frame3);
}
else {
frame3 = frame2;
}
if (writer.isOpened()) {
writer.write(frame3);
}
if (outfile.empty()) {
imshow("output", frame3);
char key = (char) waitKey(1);
if (key == 27)
break;
else if (key == 'm') {
ocl::setUseOpenCL(!cv::ocl::useOpenCL());
cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL enabled" : "CPU") << " mode\n";
}
}
fps_counter.NewFrame();
}
return EXIT_SUCCESS;
}