From 3c376d9366a236acd11366eaf41eac3f53b2def1 Mon Sep 17 00:00:00 2001
From: Scheaven <xuepengqiang>
Date: 星期四, 03 六月 2021 16:28:12 +0800
Subject: [PATCH] add m

---
 lib/detecter_tools/darknet/image_opencv.cpp | 3073 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 1,558 insertions(+), 1,515 deletions(-)

diff --git a/lib/detecter_tools/darknet/image_opencv.cpp b/lib/detecter_tools/darknet/image_opencv.cpp
index a3637e7..f9615cb 100644
--- a/lib/detecter_tools/darknet/image_opencv.cpp
+++ b/lib/detecter_tools/darknet/image_opencv.cpp
@@ -1,1515 +1,1558 @@
-#include "image_opencv.h"
-#include <iostream>
-
-#ifdef OPENCV
-#include "utils.h"
-
-#include <cstdio>
-#include <cstdlib>
-#include <cmath>
-#include <string>
-#include <vector>
-#include <fstream>
-#include <algorithm>
-#include <atomic>
-
-#include <opencv2/core/version.hpp>
-#include <opencv2/imgproc/imgproc.hpp>
-#include <opencv2/opencv.hpp>
-#include <opencv2/opencv_modules.hpp>
-
-#include <opencv2/highgui/highgui.hpp>
-#include <opencv2/video/video.hpp>
-
-// includes for OpenCV >= 3.x
-#ifndef CV_VERSION_EPOCH
-#include <opencv2/core/types.hpp>
-#include <opencv2/videoio/videoio.hpp>
-#include <opencv2/imgcodecs/imgcodecs.hpp>
-#endif
-
-// OpenCV includes for OpenCV 2.x
-#ifdef CV_VERSION_EPOCH
-#include <opencv2/highgui/highgui_c.h>
-#include <opencv2/imgproc/imgproc_c.h>
-#include <opencv2/core/types_c.h>
-#include <opencv2/core/version.hpp>
-#endif
-
-//using namespace cv;
-
-using std::cerr;
-using std::endl;
-
-#ifdef DEBUG
-#define OCV_D "d"
-#else
-#define OCV_D
-#endif//DEBUG
-
-
-// OpenCV libraries
-#ifndef CV_VERSION_EPOCH
-#define OPENCV_VERSION CVAUX_STR(CV_VERSION_MAJOR)"" CVAUX_STR(CV_VERSION_MINOR)"" CVAUX_STR(CV_VERSION_REVISION) OCV_D
-#ifndef USE_CMAKE_LIBS
-#pragma comment(lib, "opencv_world" OPENCV_VERSION ".lib")
-#endif    // USE_CMAKE_LIBS
-#else   // CV_VERSION_EPOCH
-#define OPENCV_VERSION CVAUX_STR(CV_VERSION_EPOCH)"" CVAUX_STR(CV_VERSION_MAJOR)"" CVAUX_STR(CV_VERSION_MINOR) OCV_D
-#ifndef USE_CMAKE_LIBS
-#pragma comment(lib, "opencv_core" OPENCV_VERSION ".lib")
-#pragma comment(lib, "opencv_imgproc" OPENCV_VERSION ".lib")
-#pragma comment(lib, "opencv_highgui" OPENCV_VERSION ".lib")
-#endif    // USE_CMAKE_LIBS
-#endif    // CV_VERSION_EPOCH
-
-#include "http_stream.h"
-
-#ifndef CV_RGB
-#define CV_RGB(r, g, b) cvScalar( (b), (g), (r), 0 )
-#endif
-
-#ifndef CV_FILLED
-#define CV_FILLED cv::FILLED
-#endif
-
-#ifndef CV_AA
-#define CV_AA cv::LINE_AA
-#endif
-
-extern "C" {
-
-    //struct mat_cv : cv::Mat {  };
-    //struct cap_cv : cv::VideoCapture { };
-    //struct write_cv : cv::VideoWriter {  };
-
-    //struct mat_cv : cv::Mat { int a[0]; };
-    //struct cap_cv : cv::VideoCapture { int a[0]; };
-    //struct write_cv : cv::VideoWriter { int a[0]; };
-
-// ====================================================================
-// cv::Mat
-// ====================================================================
-    image mat_to_image(cv::Mat mat);
-    cv::Mat image_to_mat(image img);
-//    image ipl_to_image(mat_cv* src);
-//    mat_cv *image_to_ipl(image img);
-//    cv::Mat ipl_to_mat(IplImage *ipl);
-//    IplImage *mat_to_ipl(cv::Mat mat);
-
-
-extern "C" mat_cv *load_image_mat_cv(const char *filename, int flag)
-{
-    cv::Mat *mat_ptr = NULL;
-    try {
-        cv::Mat mat = cv::imread(filename, flag);
-        if (mat.empty())
-        {
-            std::string shrinked_filename = filename;
-            if (shrinked_filename.length() > 1024) {
-                shrinked_filename.resize(1024);
-                shrinked_filename = std::string("name is too long: ") + shrinked_filename;
-            }
-            cerr << "Cannot load image " << shrinked_filename << std::endl;
-            std::ofstream bad_list("bad.list", std::ios::out | std::ios::app);
-            bad_list << shrinked_filename << std::endl;
-            //if (check_mistakes) getchar();
-            return NULL;
-        }
-        cv::Mat dst;
-        if (mat.channels() == 3) cv::cvtColor(mat, dst, cv::COLOR_RGB2BGR);
-        else if (mat.channels() == 4) cv::cvtColor(mat, dst, cv::COLOR_RGBA2BGRA);
-        else dst = mat;
-
-        mat_ptr = new cv::Mat(dst);
-
-        return (mat_cv *)mat_ptr;
-    }
-    catch (...) {
-        cerr << "OpenCV exception: load_image_mat_cv \n";
-    }
-    if (mat_ptr) delete mat_ptr;
-    return NULL;
-}
-// ----------------------------------------
-
-cv::Mat load_image_mat(char *filename, int channels)
-{
-    int flag = cv::IMREAD_UNCHANGED;
-    if (channels == 0) flag = cv::IMREAD_COLOR;
-    else if (channels == 1) flag = cv::IMREAD_GRAYSCALE;
-    else if (channels == 3) flag = cv::IMREAD_COLOR;
-    else {
-        fprintf(stderr, "OpenCV can't force load with %d channels\n", channels);
-    }
-    //flag |= IMREAD_IGNORE_ORIENTATION;    // un-comment it if you want
-
-    cv::Mat *mat_ptr = (cv::Mat *)load_image_mat_cv(filename, flag);
-
-    if (mat_ptr == NULL) {
-        return cv::Mat();
-    }
-    cv::Mat mat = *mat_ptr;
-    delete mat_ptr;
-
-    return mat;
-}
-// ----------------------------------------
-
-extern "C" image load_image_cv(char *filename, int channels)
-{
-    cv::Mat mat = load_image_mat(filename, channels);
-
-    if (mat.empty()) {
-        return make_image(10, 10, channels);
-    }
-    return mat_to_image(mat);
-}
-// ----------------------------------------
-
-extern "C" image load_image_resize(char *filename, int w, int h, int c, image *im)
-{
-    image out;
-    try {
-        cv::Mat loaded_image = load_image_mat(filename, c);
-
-        *im = mat_to_image(loaded_image);
-
-        cv::Mat resized(h, w, CV_8UC3);
-        cv::resize(loaded_image, resized, cv::Size(w, h), 0, 0, cv::INTER_LINEAR);
-        out = mat_to_image(resized);
-    }
-    catch (...) {
-        cerr << " OpenCV exception: load_image_resize() can't load image %s " << filename << " \n";
-        out = make_image(w, h, c);
-        *im = make_image(w, h, c);
-    }
-    return out;
-}
-// ----------------------------------------
-
-extern "C" int get_width_mat(mat_cv *mat)
-{
-    if (mat == NULL) {
-        cerr << " Pointer is NULL in get_width_mat() \n";
-        return 0;
-    }
-    return ((cv::Mat *)mat)->cols;
-}
-// ----------------------------------------
-
-extern "C" int get_height_mat(mat_cv *mat)
-{
-    if (mat == NULL) {
-        cerr << " Pointer is NULL in get_height_mat() \n";
-        return 0;
-    }
-    return ((cv::Mat *)mat)->rows;
-}
-// ----------------------------------------
-
-extern "C" void release_mat(mat_cv **mat)
-{
-    try {
-        cv::Mat **mat_ptr = (cv::Mat **)mat;
-        if (*mat_ptr) delete *mat_ptr;
-        *mat_ptr = NULL;
-    }
-    catch (...) {
-        cerr << "OpenCV exception: release_mat \n";
-    }
-}
-
-// ====================================================================
-// IplImage
-// ====================================================================
-/*
-extern "C" int get_width_cv(mat_cv *ipl_src)
-{
-    IplImage *ipl = (IplImage *)ipl_src;
-    return ipl->width;
-}
-// ----------------------------------------
-
-extern "C" int get_height_cv(mat_cv *ipl_src)
-{
-    IplImage *ipl = (IplImage *)ipl_src;
-    return ipl->height;
-}
-// ----------------------------------------
-
-extern "C" void release_ipl(mat_cv **ipl)
-{
-    IplImage **ipl_img = (IplImage **)ipl;
-    if (*ipl_img) cvReleaseImage(ipl_img);
-    *ipl_img = NULL;
-}
-// ----------------------------------------
-
-// ====================================================================
-// image-to-ipl, ipl-to-image, image_to_mat, mat_to_image
-// ====================================================================
-
-extern "C" mat_cv *image_to_ipl(image im)
-{
-    int x, y, c;
-    IplImage *disp = cvCreateImage(cvSize(im.w, im.h), IPL_DEPTH_8U, im.c);
-    int step = disp->widthStep;
-    for (y = 0; y < im.h; ++y) {
-        for (x = 0; x < im.w; ++x) {
-            for (c = 0; c < im.c; ++c) {
-                float val = im.data[c*im.h*im.w + y*im.w + x];
-                disp->imageData[y*step + x*im.c + c] = (unsigned char)(val * 255);
-            }
-        }
-    }
-    return (mat_cv *)disp;
-}
-// ----------------------------------------
-
-extern "C" image ipl_to_image(mat_cv* src_ptr)
-{
-    IplImage* src = (IplImage*)src_ptr;
-    int h = src->height;
-    int w = src->width;
-    int c = src->nChannels;
-    image im = make_image(w, h, c);
-    unsigned char *data = (unsigned char *)src->imageData;
-    int step = src->widthStep;
-    int i, j, k;
-
-    for (i = 0; i < h; ++i) {
-        for (k = 0; k < c; ++k) {
-            for (j = 0; j < w; ++j) {
-                im.data[k*w*h + i*w + j] = data[i*step + j*c + k] / 255.;
-            }
-        }
-    }
-    return im;
-}
-// ----------------------------------------
-
-cv::Mat ipl_to_mat(IplImage *ipl)
-{
-    Mat m = cvarrToMat(ipl, true);
-    return m;
-}
-// ----------------------------------------
-
-IplImage *mat_to_ipl(cv::Mat mat)
-{
-    IplImage *ipl = new IplImage;
-    *ipl = mat;
-    return ipl;
-}
-// ----------------------------------------
-*/
-
-extern "C" cv::Mat image_to_mat(image img)
-{
-    int channels = img.c;
-    int width = img.w;
-    int height = img.h;
-    cv::Mat mat = cv::Mat(height, width, CV_8UC(channels));
-    int step = mat.step;
-
-    for (int y = 0; y < img.h; ++y) {
-        for (int x = 0; x < img.w; ++x) {
-            for (int c = 0; c < img.c; ++c) {
-                float val = img.data[c*img.h*img.w + y*img.w + x];
-                mat.data[y*step + x*img.c + c] = (unsigned char)(val * 255);
-            }
-        }
-    }
-    return mat;
-}
-// ----------------------------------------
-
-extern "C" image mat_to_image(cv::Mat mat)
-{
-    int w = mat.cols;
-    int h = mat.rows;
-    int c = mat.channels();
-    image im = make_image(w, h, c);
-    unsigned char *data = (unsigned char *)mat.data;
-    int step = mat.step;
-    for (int y = 0; y < h; ++y) {
-        for (int k = 0; k < c; ++k) {
-            for (int x = 0; x < w; ++x) {
-                //uint8_t val = mat.ptr<uint8_t>(y)[c * x + k];
-                //uint8_t val = mat.at<Vec3b>(y, x).val[k];
-                //im.data[k*w*h + y*w + x] = val / 255.0f;
-
-                im.data[k*w*h + y*w + x] = data[y*step + x*c + k] / 255.0f;
-            }
-        }
-    }
-    return im;
-}
-
-image mat_to_image_cv(mat_cv *mat)
-{
-    return mat_to_image(*(cv::Mat*)mat);
-}
-
-// ====================================================================
-// Window
-// ====================================================================
-extern "C" void create_window_cv(char const* window_name, int full_screen, int width, int height)
-{
-    try {
-        int window_type = cv::WINDOW_NORMAL;
-#ifdef CV_VERSION_EPOCH // OpenCV 2.x
-        if (full_screen) window_type = CV_WINDOW_FULLSCREEN;
-#else
-        if (full_screen) window_type = cv::WINDOW_FULLSCREEN;
-#endif
-        cv::namedWindow(window_name, window_type);
-        cv::moveWindow(window_name, 0, 0);
-        cv::resizeWindow(window_name, width, height);
-    }
-    catch (...) {
-        cerr << "OpenCV exception: create_window_cv \n";
-    }
-}
-// ----------------------------------------
-
-extern "C" void destroy_all_windows_cv()
-{
-    try {
-        cv::destroyAllWindows();
-    }
-    catch (...) {
-        cerr << "OpenCV exception: destroy_all_windows_cv \n";
-    }
-}
-// ----------------------------------------
-
-extern "C" int wait_key_cv(int delay)
-{
-    try {
-        return cv::waitKey(delay);
-    }
-    catch (...) {
-        cerr << "OpenCV exception: wait_key_cv \n";
-    }
-    return -1;
-}
-// ----------------------------------------
-
-extern "C" int wait_until_press_key_cv()
-{
-    return wait_key_cv(0);
-}
-// ----------------------------------------
-
-extern "C" void make_window(char *name, int w, int h, int fullscreen)
-{
-    try {
-        cv::namedWindow(name, cv::WINDOW_NORMAL);
-        if (fullscreen) {
-#ifdef CV_VERSION_EPOCH // OpenCV 2.x
-            cv::setWindowProperty(name, cv::WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
-#else
-            cv::setWindowProperty(name, cv::WND_PROP_FULLSCREEN, cv::WINDOW_FULLSCREEN);
-#endif
-        }
-        else {
-            cv::resizeWindow(name, w, h);
-            if (strcmp(name, "Demo") == 0) cv::moveWindow(name, 0, 0);
-        }
-    }
-    catch (...) {
-        cerr << "OpenCV exception: make_window \n";
-    }
-}
-// ----------------------------------------
-
-static float get_pixel(image m, int x, int y, int c)
-{
-    assert(x < m.w && y < m.h && c < m.c);
-    return m.data[c*m.h*m.w + y*m.w + x];
-}
-// ----------------------------------------
-
-extern "C" void show_image_cv(image p, const char *name)
-{
-    try {
-        image copy = copy_image(p);
-        constrain_image(copy);
-
-        cv::Mat mat = image_to_mat(copy);
-        if (mat.channels() == 3) cv::cvtColor(mat, mat, cv::COLOR_RGB2BGR);
-        else if (mat.channels() == 4) cv::cvtColor(mat, mat, cv::COLOR_RGBA2BGR);
-        cv::namedWindow(name, cv::WINDOW_NORMAL);
-        cv::imshow(name, mat);
-        free_image(copy);
-    }
-    catch (...) {
-        cerr << "OpenCV exception: show_image_cv \n";
-    }
-}
-// ----------------------------------------
-
-/*
-extern "C" void show_image_cv_ipl(mat_cv *disp, const char *name)
-{
-    if (disp == NULL) return;
-    char buff[256];
-    sprintf(buff, "%s", name);
-    cv::namedWindow(buff, WINDOW_NORMAL);
-    cvShowImage(buff, disp);
-}
-// ----------------------------------------
-*/
-
-extern "C" void show_image_mat(mat_cv *mat_ptr, const char *name)
-{
-    try {
-        if (mat_ptr == NULL) return;
-        cv::Mat &mat = *(cv::Mat *)mat_ptr;
-        cv::namedWindow(name, cv::WINDOW_NORMAL);
-        cv::imshow(name, mat);
-    }
-    catch (...) {
-        cerr << "OpenCV exception: show_image_mat \n";
-    }
-}
-
-// ====================================================================
-// Video Writer
-// ====================================================================
-extern "C" write_cv *create_video_writer(char *out_filename, char c1, char c2, char c3, char c4, int fps, int width, int height, int is_color)
-{
-    try {
-    cv::VideoWriter * output_video_writer =
-#ifdef CV_VERSION_EPOCH
-        new cv::VideoWriter(out_filename, CV_FOURCC(c1, c2, c3, c4), fps, cv::Size(width, height), is_color);
-#else
-        new cv::VideoWriter(out_filename, cv::VideoWriter::fourcc(c1, c2, c3, c4), fps, cv::Size(width, height), is_color);
-#endif
-
-    return (write_cv *)output_video_writer;
-    }
-    catch (...) {
-        cerr << "OpenCV exception: create_video_writer \n";
-    }
-    return NULL;
-}
-
-extern "C" void write_frame_cv(write_cv *output_video_writer, mat_cv *mat)
-{
-    try {
-        cv::VideoWriter *out = (cv::VideoWriter *)output_video_writer;
-        out->write(*(cv::Mat*)mat);
-    }
-    catch (...) {
-        cerr << "OpenCV exception: write_frame_cv \n";
-    }
-}
-
-extern "C" void release_video_writer(write_cv **output_video_writer)
-{
-    try {
-        if (output_video_writer) {
-            std::cout << " closing...";
-            cv::VideoWriter *out = *(cv::VideoWriter **)output_video_writer;
-            out->release();
-            delete out;
-            output_video_writer = NULL;
-            std::cout << " closed!";
-        }
-        else {
-            cerr << "OpenCV exception: output_video_writer isn't created \n";
-        }
-    }
-    catch (...) {
-        cerr << "OpenCV exception: release_video_writer \n";
-    }
-}
-
-/*
-extern "C" void *open_video_stream(const char *f, int c, int w, int h, int fps)
-{
-    VideoCapture *cap;
-    if(f) cap = new VideoCapture(f);
-    else cap = new VideoCapture(c);
-    if(!cap->isOpened()) return 0;
-    if(w) cap->set(CV_CAP_PROP_FRAME_WIDTH, w);
-    if(h) cap->set(CV_CAP_PROP_FRAME_HEIGHT, w);
-    if(fps) cap->set(CV_CAP_PROP_FPS, w);
-    return (void *) cap;
-}
-
-
-extern "C" image get_image_from_stream(void *p)
-{
-    VideoCapture *cap = (VideoCapture *)p;
-    Mat m;
-    *cap >> m;
-    if(m.empty()) return make_empty_image(0,0,0);
-    return mat_to_image(m);
-}
-
-extern "C" int show_image_cv(image im, const char* name, int ms)
-{
-    Mat m = image_to_mat(im);
-    imshow(name, m);
-    int c = waitKey(ms);
-    if (c != -1) c = c%256;
-    return c;
-}
-*/
-
-
-// ====================================================================
-// Video Capture
-// ====================================================================
-
-extern "C" cap_cv* get_capture_video_stream(const char *path) {
-    cv::VideoCapture* cap = NULL;
-    try {
-        cap = new cv::VideoCapture(path);
-    }
-    catch (...) {
-        cerr << " OpenCV exception: video-stream " << path << " can't be opened! \n";
-    }
-    return (cap_cv*)cap;
-}
-// ----------------------------------------
-
-extern "C" cap_cv* get_capture_webcam(int index)
-{
-    cv::VideoCapture* cap = NULL;
-    try {
-        cap = new cv::VideoCapture(index);
-        //cap->set(CV_CAP_PROP_FRAME_WIDTH, 1280);
-        //cap->set(CV_CAP_PROP_FRAME_HEIGHT, 960);
-    }
-    catch (...) {
-        cerr << " OpenCV exception: Web-camera " << index << " can't be opened! \n";
-    }
-    return (cap_cv*)cap;
-}
-// ----------------------------------------
-
-extern "C" void release_capture(cap_cv* cap)
-{
-    try {
-        cv::VideoCapture *cpp_cap = (cv::VideoCapture *)cap;
-        delete cpp_cap;
-    }
-    catch (...) {
-        cerr << " OpenCV exception: cv::VideoCapture " << cap << " can't be released! \n";
-    }
-}
-// ----------------------------------------
-
-extern "C" mat_cv* get_capture_frame_cv(cap_cv *cap) {
-    cv::Mat *mat = NULL;
-    try {
-        mat = new cv::Mat();
-        if (cap) {
-            cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
-            if (cpp_cap.isOpened())
-            {
-                cpp_cap >> *mat;
-            }
-            else std::cout << " Video-stream stopped! \n";
-        }
-        else cerr << " cv::VideoCapture isn't created \n";
-    }
-    catch (...) {
-        std::cout << " OpenCV exception: Video-stream stoped! \n";
-    }
-    return (mat_cv *)mat;
-}
-// ----------------------------------------
-
-extern "C" int get_stream_fps_cpp_cv(cap_cv *cap)
-{
-    int fps = 25;
-    try {
-        cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
-#ifndef CV_VERSION_EPOCH    // OpenCV 3.x
-        fps = cpp_cap.get(cv::CAP_PROP_FPS);
-#else                        // OpenCV 2.x
-        fps = cpp_cap.get(CV_CAP_PROP_FPS);
-#endif
-    }
-    catch (...) {
-        cerr << " Can't get FPS of source videofile. For output video FPS = 25 by default. \n";
-    }
-    return fps;
-}
-// ----------------------------------------
-
-extern "C" double get_capture_property_cv(cap_cv *cap, int property_id)
-{
-    try {
-        cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
-        return cpp_cap.get(property_id);
-    }
-    catch (...) {
-        cerr << " OpenCV exception: Can't get property of source video-stream. \n";
-    }
-    return 0;
-}
-// ----------------------------------------
-
-extern "C" double get_capture_frame_count_cv(cap_cv *cap)
-{
-    try {
-        cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
-#ifndef CV_VERSION_EPOCH    // OpenCV 3.x
-        return cpp_cap.get(cv::CAP_PROP_FRAME_COUNT);
-#else                        // OpenCV 2.x
-        return cpp_cap.get(CV_CAP_PROP_FRAME_COUNT);
-#endif
-    }
-    catch (...) {
-        cerr << " OpenCV exception: Can't get CAP_PROP_FRAME_COUNT of source videofile. \n";
-    }
-    return 0;
-}
-// ----------------------------------------
-
-extern "C" int set_capture_property_cv(cap_cv *cap, int property_id, double value)
-{
-    try {
-        cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
-        return cpp_cap.set(property_id, value);
-    }
-    catch (...) {
-        cerr << " Can't set property of source video-stream. \n";
-    }
-    return false;
-}
-// ----------------------------------------
-
-extern "C" int set_capture_position_frame_cv(cap_cv *cap, int index)
-{
-    try {
-        cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
-#ifndef CV_VERSION_EPOCH    // OpenCV 3.x
-        return cpp_cap.set(cv::CAP_PROP_POS_FRAMES, index);
-#else                        // OpenCV 2.x
-        return cpp_cap.set(CV_CAP_PROP_POS_FRAMES, index);
-#endif
-    }
-    catch (...) {
-        cerr << " Can't set CAP_PROP_POS_FRAMES of source videofile. \n";
-    }
-    return false;
-}
-// ----------------------------------------
-
-
-
-// ====================================================================
-// ... Video Capture
-// ====================================================================
-
-extern "C" image get_image_from_stream_cpp(cap_cv *cap)
-{
-    cv::Mat *src = NULL;
-    static int once = 1;
-    if (once) {
-        once = 0;
-        do {
-            if (src) delete src;
-            src = (cv::Mat*)get_capture_frame_cv(cap);
-            if (!src) return make_empty_image(0, 0, 0);
-        } while (src->cols < 1 || src->rows < 1 || src->channels() < 1);
-        printf("Video stream: %d x %d \n", src->cols, src->rows);
-    }
-    else
-        src = (cv::Mat*)get_capture_frame_cv(cap);
-
-    if (!src) return make_empty_image(0, 0, 0);
-    image im = mat_to_image(*src);
-    rgbgr_image(im);
-    if (src) delete src;
-    return im;
-}
-// ----------------------------------------
-
-extern "C" int wait_for_stream(cap_cv *cap, cv::Mat* src, int dont_close)
-{
-    if (!src) {
-        if (dont_close) src = new cv::Mat(416, 416, CV_8UC(3)); // cvCreateImage(cvSize(416, 416), IPL_DEPTH_8U, 3);
-        else return 0;
-    }
-    if (src->cols < 1 || src->rows < 1 || src->channels() < 1) {
-        if (dont_close) {
-            delete src;// cvReleaseImage(&src);
-            int z = 0;
-            for (z = 0; z < 20; ++z) {
-                src = (cv::Mat*)get_capture_frame_cv(cap);
-                delete src;// cvReleaseImage(&src);
-            }
-            src = new cv::Mat(416, 416, CV_8UC(3)); // cvCreateImage(cvSize(416, 416), IPL_DEPTH_8U, 3);
-        }
-        else return 0;
-    }
-    return 1;
-}
-// ----------------------------------------
-
-extern "C" image get_image_from_stream_resize(cap_cv *cap, int w, int h, int c, mat_cv** in_img, int dont_close)
-{
-    c = c ? c : 3;
-    cv::Mat *src = NULL;
-
-    static int once = 1;
-    if (once) {
-        once = 0;
-        do {
-            if (src) delete src;
-            src = (cv::Mat*)get_capture_frame_cv(cap);
-            if (!src) return make_empty_image(0, 0, 0);
-        } while (src->cols < 1 || src->rows < 1 || src->channels() < 1);
-        printf("Video stream: %d x %d \n", src->cols, src->rows);
-    }
-    else
-        src = (cv::Mat*)get_capture_frame_cv(cap);
-
-    if (!wait_for_stream(cap, src, dont_close)) return make_empty_image(0, 0, 0);
-
-    *(cv::Mat **)in_img = src;
-
-    cv::Mat new_img = cv::Mat(h, w, CV_8UC(c));
-    cv::resize(*src, new_img, new_img.size(), 0, 0, cv::INTER_LINEAR);
-    if (c>1) cv::cvtColor(new_img, new_img, cv::COLOR_RGB2BGR);
-    image im = mat_to_image(new_img);
-
-    //show_image_cv(im, "im");
-    //show_image_mat(*in_img, "in_img");
-    return im;
-}
-// ----------------------------------------
-
-extern "C" image get_image_from_stream_letterbox(cap_cv *cap, int w, int h, int c, mat_cv** in_img, int dont_close)
-{
-    c = c ? c : 3;
-    cv::Mat *src = NULL;
-    static int once = 1;
-    if (once) {
-        once = 0;
-        do {
-            if (src) delete src;
-            src = (cv::Mat*)get_capture_frame_cv(cap);
-            if (!src) return make_empty_image(0, 0, 0);
-        } while (src->cols < 1 || src->rows < 1 || src->channels() < 1);
-        printf("Video stream: %d x %d \n", src->cols, src->rows);
-    }
-    else
-        src = (cv::Mat*)get_capture_frame_cv(cap);
-
-    if (!wait_for_stream(cap, src, dont_close)) return make_empty_image(0, 0, 0);   // passes (cv::Mat *)src while should be (cv::Mat **)src
-
-    *in_img = (mat_cv *)new cv::Mat(src->rows, src->cols, CV_8UC(c));
-    cv::resize(*src, **(cv::Mat**)in_img, (*(cv::Mat**)in_img)->size(), 0, 0, cv::INTER_LINEAR);
-
-    if (c>1) cv::cvtColor(*src, *src, cv::COLOR_RGB2BGR);
-    image tmp = mat_to_image(*src);
-    image im = letterbox_image(tmp, w, h);
-    free_image(tmp);
-    release_mat((mat_cv **)&src);
-
-    //show_image_cv(im, "im");
-    //show_image_mat(*in_img, "in_img");
-    return im;
-}
-// ----------------------------------------
-
-// ====================================================================
-// Image Saving
-// ====================================================================
-extern int stbi_write_png(char const *filename, int w, int h, int comp, const void  *data, int stride_in_bytes);
-extern int stbi_write_jpg(char const *filename, int x, int y, int comp, const void  *data, int quality);
-
-extern "C" void save_mat_png(cv::Mat img_src, const char *name)
-{
-    cv::Mat img_rgb;
-    if (img_src.channels() >= 3) cv::cvtColor(img_src, img_rgb, cv::COLOR_RGB2BGR);
-    stbi_write_png(name, img_rgb.cols, img_rgb.rows, 3, (char *)img_rgb.data, 0);
-}
-// ----------------------------------------
-
-extern "C" void save_mat_jpg(cv::Mat img_src, const char *name)
-{
-    cv::Mat img_rgb;
-    if (img_src.channels() >= 3) cv::cvtColor(img_src, img_rgb, cv::COLOR_RGB2BGR);
-    stbi_write_jpg(name, img_rgb.cols, img_rgb.rows, 3, (char *)img_rgb.data, 80);
-}
-// ----------------------------------------
-
-
-extern "C" void save_cv_png(mat_cv *img_src, const char *name)
-{
-    cv::Mat* img = (cv::Mat* )img_src;
-    save_mat_png(*img, name);
-}
-// ----------------------------------------
-
-extern "C" void save_cv_jpg(mat_cv *img_src, const char *name)
-{
-    cv::Mat* img = (cv::Mat*)img_src;
-    save_mat_jpg(*img, name);
-}
-// ----------------------------------------
-
-
-// ====================================================================
-// Draw Detection
-// ====================================================================
-extern "C" void draw_detections_cv_v3(mat_cv* mat, detection *dets, int num, float thresh, char **names, image **alphabet, int classes, int ext_output)
-{
-    try {
-        cv::Mat *show_img = (cv::Mat*)mat;
-        int i, j;
-        if (!show_img) return;
-        static int frame_id = 0;
-        frame_id++;
-
-        for (i = 0; i < num; ++i) {
-            char labelstr[4096] = { 0 };
-            int class_id = -1;
-            for (j = 0; j < classes; ++j) {
-                int show = strncmp(names[j], "dont_show", 9);
-                if (dets[i].prob[j] > thresh && show) {
-                    if (class_id < 0) {
-                        strcat(labelstr, names[j]);
-                        class_id = j;
-                        char buff[10];
-                        sprintf(buff, " (%2.0f%%)", dets[i].prob[j] * 100);
-                        strcat(labelstr, buff);
-                        printf("%s: %.0f%% ", names[j], dets[i].prob[j] * 100);
-                    }
-                    else {
-                        strcat(labelstr, ", ");
-                        strcat(labelstr, names[j]);
-                        printf(", %s: %.0f%% ", names[j], dets[i].prob[j] * 100);
-                    }
-                }
-            }
-            if (class_id >= 0) {
-                int width = std::max(1.0f, show_img->rows * .002f);
-
-                //if(0){
-                //width = pow(prob, 1./2.)*10+1;
-                //alphabet = 0;
-                //}
-
-                //printf("%d %s: %.0f%%\n", i, names[class_id], prob*100);
-                int offset = class_id * 123457 % classes;
-                float red = get_color(2, offset, classes);
-                float green = get_color(1, offset, classes);
-                float blue = get_color(0, offset, classes);
-                float rgb[3];
-
-                //width = prob*20+2;
-
-                rgb[0] = red;
-                rgb[1] = green;
-                rgb[2] = blue;
-                box b = dets[i].bbox;
-                if (std::isnan(b.w) || std::isinf(b.w)) b.w = 0.5;
-                if (std::isnan(b.h) || std::isinf(b.h)) b.h = 0.5;
-                if (std::isnan(b.x) || std::isinf(b.x)) b.x = 0.5;
-                if (std::isnan(b.y) || std::isinf(b.y)) b.y = 0.5;
-                b.w = (b.w < 1) ? b.w : 1;
-                b.h = (b.h < 1) ? b.h : 1;
-                b.x = (b.x < 1) ? b.x : 1;
-                b.y = (b.y < 1) ? b.y : 1;
-                //printf("%f %f %f %f\n", b.x, b.y, b.w, b.h);
-
-                int left = (b.x - b.w / 2.)*show_img->cols;
-                int right = (b.x + b.w / 2.)*show_img->cols;
-                int top = (b.y - b.h / 2.)*show_img->rows;
-                int bot = (b.y + b.h / 2.)*show_img->rows;
-
-                if (left < 0) left = 0;
-                if (right > show_img->cols - 1) right = show_img->cols - 1;
-                if (top < 0) top = 0;
-                if (bot > show_img->rows - 1) bot = show_img->rows - 1;
-
-                //int b_x_center = (left + right) / 2;
-                //int b_y_center = (top + bot) / 2;
-                //int b_width = right - left;
-                //int b_height = bot - top;
-                //sprintf(labelstr, "%d x %d - w: %d, h: %d", b_x_center, b_y_center, b_width, b_height);
-
-                float const font_size = show_img->rows / 1000.F;
-                cv::Size const text_size = cv::getTextSize(labelstr, cv::FONT_HERSHEY_COMPLEX_SMALL, font_size, 1, 0);
-                cv::Point pt1, pt2, pt_text, pt_text_bg1, pt_text_bg2;
-                pt1.x = left;
-                pt1.y = top;
-                pt2.x = right;
-                pt2.y = bot;
-                pt_text.x = left;
-                pt_text.y = top - 4;// 12;
-                pt_text_bg1.x = left;
-                pt_text_bg1.y = top - (3 + 18 * font_size);
-                pt_text_bg2.x = right;
-                if ((right - left) < text_size.width) pt_text_bg2.x = left + text_size.width;
-                pt_text_bg2.y = top;
-                cv::Scalar color;
-                color.val[0] = red * 256;
-                color.val[1] = green * 256;
-                color.val[2] = blue * 256;
-
-                // you should create directory: result_img
-                //static int copied_frame_id = -1;
-                //static IplImage* copy_img = NULL;
-                //if (copied_frame_id != frame_id) {
-                //    copied_frame_id = frame_id;
-                //    if(copy_img == NULL) copy_img = cvCreateImage(cvSize(show_img->width, show_img->height), show_img->depth, show_img->nChannels);
-                //    cvCopy(show_img, copy_img, 0);
-                //}
-                //static int img_id = 0;
-                //img_id++;
-                //char image_name[1024];
-                //sprintf(image_name, "result_img/img_%d_%d_%d_%s.jpg", frame_id, img_id, class_id, names[class_id]);
-                //CvRect rect = cvRect(pt1.x, pt1.y, pt2.x - pt1.x, pt2.y - pt1.y);
-                //cvSetImageROI(copy_img, rect);
-                //cvSaveImage(image_name, copy_img, 0);
-                //cvResetImageROI(copy_img);
-
-                cv::rectangle(*show_img, pt1, pt2, color, width, 8, 0);
-                if (ext_output)
-                    printf("\t(left_x: %4.0f   top_y: %4.0f   width: %4.0f   height: %4.0f)\n",
-                    (float)left, (float)top, b.w*show_img->cols, b.h*show_img->rows);
-                else
-                    printf("\n");
-
-                cv::rectangle(*show_img, pt_text_bg1, pt_text_bg2, color, width, 8, 0);
-                cv::rectangle(*show_img, pt_text_bg1, pt_text_bg2, color, CV_FILLED, 8, 0);    // filled
-                cv::Scalar black_color = CV_RGB(0, 0, 0);
-                cv::putText(*show_img, labelstr, pt_text, cv::FONT_HERSHEY_COMPLEX_SMALL, font_size, black_color, 2 * font_size, CV_AA);
-                // cv::FONT_HERSHEY_COMPLEX_SMALL, cv::FONT_HERSHEY_SIMPLEX
-            }
-        }
-        if (ext_output) {
-            fflush(stdout);
-        }
-    }
-    catch (...) {
-        cerr << "OpenCV exception: draw_detections_cv_v3() \n";
-    }
-}
-// ----------------------------------------
-
-// ====================================================================
-// Draw Loss & Accuracy chart
-// ====================================================================
-extern "C" mat_cv* draw_train_chart(char *windows_name, float max_img_loss, int max_batches, int number_of_lines, int img_size, int dont_show, char* chart_path)
-{
-    int img_offset = 60;
-    int draw_size = img_size - img_offset;
-    cv::Mat *img_ptr = new cv::Mat(img_size, img_size, CV_8UC3, CV_RGB(255, 255, 255));
-    cv::Mat &img = *img_ptr;
-    cv::Point pt1, pt2, pt_text;
-
-    try {
-        // load chart from file
-        if (chart_path != NULL && chart_path[0] != '\0') {
-            *img_ptr = cv::imread(chart_path);
-        }
-        else {
-            // draw new chart
-            char char_buff[100];
-            int i;
-            // vertical lines
-            pt1.x = img_offset; pt2.x = img_size, pt_text.x = 30;
-            for (i = 1; i <= number_of_lines; ++i) {
-                pt1.y = pt2.y = (float)i * draw_size / number_of_lines;
-                cv::line(img, pt1, pt2, CV_RGB(224, 224, 224), 1, 8, 0);
-                if (i % 10 == 0) {
-                    sprintf(char_buff, "%2.1f", max_img_loss*(number_of_lines - i) / number_of_lines);
-                    pt_text.y = pt1.y + 3;
-
-                    cv::putText(img, char_buff, pt_text, cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 0), 1, CV_AA);
-                    cv::line(img, pt1, pt2, CV_RGB(128, 128, 128), 1, 8, 0);
-                }
-            }
-            // horizontal lines
-            pt1.y = draw_size; pt2.y = 0, pt_text.y = draw_size + 15;
-            for (i = 0; i <= number_of_lines; ++i) {
-                pt1.x = pt2.x = img_offset + (float)i * draw_size / number_of_lines;
-                cv::line(img, pt1, pt2, CV_RGB(224, 224, 224), 1, 8, 0);
-                if (i % 10 == 0) {
-                    sprintf(char_buff, "%d", max_batches * i / number_of_lines);
-                    pt_text.x = pt1.x - 20;
-                    cv::putText(img, char_buff, pt_text, cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 0), 1, CV_AA);
-                    cv::line(img, pt1, pt2, CV_RGB(128, 128, 128), 1, 8, 0);
-                }
-            }
-
-            cv::putText(img, "Loss", cv::Point(10, 55), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 255), 1, CV_AA);
-            cv::putText(img, "Iteration number", cv::Point(draw_size / 2, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 0), 1, CV_AA);
-            char max_batches_buff[100];
-            sprintf(max_batches_buff, "in cfg max_batches=%d", max_batches);
-            cv::putText(img, max_batches_buff, cv::Point(draw_size - 195, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 0), 1, CV_AA);
-            cv::putText(img, "Press 's' to save : chart.png", cv::Point(5, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 0), 1, CV_AA);
-        }
-
-        if (!dont_show) {
-            printf(" If error occurs - run training with flag: -dont_show \n");
-            cv::namedWindow(windows_name, cv::WINDOW_NORMAL);
-            cv::moveWindow(windows_name, 0, 0);
-            cv::resizeWindow(windows_name, img_size, img_size);
-            cv::imshow(windows_name, img);
-            cv::waitKey(20);
-        }
-    }
-    catch (...) {
-        cerr << "OpenCV exception: draw_train_chart() \n";
-    }
-    return (mat_cv*)img_ptr;
-}
-// ----------------------------------------
-
-extern "C" void draw_train_loss(char *windows_name, mat_cv* img_src, int img_size, float avg_loss, float max_img_loss, int current_batch, int max_batches,
-    float precision, int draw_precision, char *accuracy_name, int dont_show, int mjpeg_port, double time_remaining)
-{
-    try {
-        cv::Mat &img = *(cv::Mat*)img_src;
-        int img_offset = 60;
-        int draw_size = img_size - img_offset;
-        char char_buff[100];
-        cv::Point pt1, pt2;
-        pt1.x = img_offset + draw_size * (float)current_batch / max_batches;
-        pt1.y = draw_size * (1 - avg_loss / max_img_loss);
-        if (pt1.y < 0) pt1.y = 1;
-        cv::circle(img, pt1, 1, CV_RGB(0, 0, 255), CV_FILLED, 8, 0);
-
-        // precision
-        if (draw_precision) {
-            static float old_precision = 0;
-            static float max_precision = 0;
-            static int iteration_old = 0;
-            static int text_iteration_old = 0;
-            if (iteration_old == 0)
-                cv::putText(img, accuracy_name, cv::Point(10, 12), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 0, 0), 1, CV_AA);
-
-	    if (iteration_old != 0){
-            	cv::line(img,
-                    cv::Point(img_offset + draw_size * (float)iteration_old / max_batches, draw_size * (1 - old_precision)),
-                    cv::Point(img_offset + draw_size * (float)current_batch / max_batches, draw_size * (1 - precision)),
-                    CV_RGB(255, 0, 0), 1, 8, 0);
-	    }
-
-            sprintf(char_buff, "%2.1f%% ", precision * 100);
-            cv::putText(img, char_buff, cv::Point(10, 28), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 255, 255), 5, CV_AA);
-            cv::putText(img, char_buff, cv::Point(10, 28), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(200, 0, 0), 1, CV_AA);
-
-            if ((std::fabs(old_precision - precision) > 0.1)  || (max_precision < precision) || (current_batch - text_iteration_old) >= max_batches / 10) {
-                text_iteration_old = current_batch;
-                max_precision = std::max(max_precision, precision);
-                sprintf(char_buff, "%2.0f%% ", precision * 100);
-                cv::putText(img, char_buff, cv::Point(pt1.x - 30, draw_size * (1 - precision) + 15), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 255, 255), 5, CV_AA);
-                cv::putText(img, char_buff, cv::Point(pt1.x - 30, draw_size * (1 - precision) + 15), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(200, 0, 0), 1, CV_AA);
-            }
-            old_precision = precision;
-            iteration_old = current_batch;
-        }
-        sprintf(char_buff, "current avg loss = %2.4f    iteration = %d    approx. time left = %2.2f hours", avg_loss, current_batch, time_remaining);
-        pt1.x = 15, pt1.y = draw_size + 18;
-        pt2.x = pt1.x + 800, pt2.y = pt1.y + 20;
-        cv::rectangle(img, pt1, pt2, CV_RGB(255, 255, 255), CV_FILLED, 8, 0);
-        pt1.y += 15;
-        cv::putText(img, char_buff, pt1, cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 100), 1, CV_AA);
-
-        int k = 0;
-        if (!dont_show) {
-            cv::imshow(windows_name, img);
-            k = cv::waitKey(20);
-        }
-        static int old_batch = 0;
-        if (k == 's' || current_batch == (max_batches - 1) || (current_batch / 100 > old_batch / 100)) {
-            old_batch = current_batch;
-            save_mat_png(img, "chart.png");
-            save_mat_png(img, windows_name);
-            cv::putText(img, "- Saved", cv::Point(260, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 0, 0), 1, CV_AA);
-        }
-        else
-            cv::putText(img, "- Saved", cv::Point(260, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 255, 255), 1, CV_AA);
-
-        if (mjpeg_port > 0) send_mjpeg((mat_cv *)&img, mjpeg_port, 500000, 70);
-    }
-    catch (...) {
-        cerr << "OpenCV exception: draw_train_loss() \n";
-    }
-}
-// ----------------------------------------
-
-
-// ====================================================================
-// Data augmentation
-// ====================================================================
-
-extern "C" image image_data_augmentation(mat_cv* mat, int w, int h,
-    int pleft, int ptop, int swidth, int sheight, int flip,
-    float dhue, float dsat, float dexp,
-    int gaussian_noise, int blur, int num_boxes, float *truth)
-{
-    image out;
-    try {
-        cv::Mat img = *(cv::Mat *)mat;
-
-        // crop
-        cv::Rect src_rect(pleft, ptop, swidth, sheight);
-        cv::Rect img_rect(cv::Point2i(0, 0), img.size());
-        cv::Rect new_src_rect = src_rect & img_rect;
-
-        cv::Rect dst_rect(cv::Point2i(std::max<int>(0, -pleft), std::max<int>(0, -ptop)), new_src_rect.size());
-        cv::Mat sized;
-
-        if (src_rect.x == 0 && src_rect.y == 0 && src_rect.size() == img.size()) {
-            cv::resize(img, sized, cv::Size(w, h), 0, 0, cv::INTER_LINEAR);
-        }
-        else {
-            cv::Mat cropped(src_rect.size(), img.type());
-            //cropped.setTo(cv::Scalar::all(0));
-            cropped.setTo(cv::mean(img));
-
-            img(new_src_rect).copyTo(cropped(dst_rect));
-
-            // resize
-            cv::resize(cropped, sized, cv::Size(w, h), 0, 0, cv::INTER_LINEAR);
-        }
-
-        // flip
-        if (flip) {
-            cv::Mat cropped;
-            cv::flip(sized, cropped, 1);    // 0 - x-axis, 1 - y-axis, -1 - both axes (x & y)
-            sized = cropped.clone();
-        }
-
-        // HSV augmentation
-        // cv::COLOR_BGR2HSV, cv::COLOR_RGB2HSV, cv::COLOR_HSV2BGR, cv::COLOR_HSV2RGB
-        if (dsat != 1 || dexp != 1 || dhue != 0) {
-            if (img.channels() >= 3)
-            {
-                cv::Mat hsv_src;
-                cvtColor(sized, hsv_src, cv::COLOR_RGB2HSV);    // RGB to HSV
-
-                std::vector<cv::Mat> hsv;
-                cv::split(hsv_src, hsv);
-
-                hsv[1] *= dsat;
-                hsv[2] *= dexp;
-                hsv[0] += 179 * dhue;
-
-                cv::merge(hsv, hsv_src);
-
-                cvtColor(hsv_src, sized, cv::COLOR_HSV2RGB);    // HSV to RGB (the same as previous)
-            }
-            else
-            {
-                sized *= dexp;
-            }
-        }
-
-        //std::stringstream window_name;
-        //window_name << "augmentation - " << ipl;
-        //cv::imshow(window_name.str(), sized);
-        //cv::waitKey(0);
-
-        if (blur) {
-            cv::Mat dst(sized.size(), sized.type());
-            if (blur == 1) {
-                cv::GaussianBlur(sized, dst, cv::Size(17, 17), 0);
-                //cv::bilateralFilter(sized, dst, 17, 75, 75);
-            }
-            else {
-                int ksize = (blur / 2) * 2 + 1;
-                cv::Size kernel_size = cv::Size(ksize, ksize);
-                cv::GaussianBlur(sized, dst, kernel_size, 0);
-                //cv::medianBlur(sized, dst, ksize);
-                //cv::bilateralFilter(sized, dst, ksize, 75, 75);
-
-                // sharpen
-                //cv::Mat img_tmp;
-                //cv::GaussianBlur(dst, img_tmp, cv::Size(), 3);
-                //cv::addWeighted(dst, 1.5, img_tmp, -0.5, 0, img_tmp);
-                //dst = img_tmp;
-            }
-            //std::cout << " blur num_boxes = " << num_boxes << std::endl;
-
-            if (blur == 1) {
-                cv::Rect img_rect(0, 0, sized.cols, sized.rows);
-                int t;
-                for (t = 0; t < num_boxes; ++t) {
-                    box b = float_to_box_stride(truth + t*(4 + 1), 1);
-                    if (!b.x) break;
-                    int left = (b.x - b.w / 2.)*sized.cols;
-                    int width = b.w*sized.cols;
-                    int top = (b.y - b.h / 2.)*sized.rows;
-                    int height = b.h*sized.rows;
-                    cv::Rect roi(left, top, width, height);
-                    roi = roi & img_rect;
-
-                    sized(roi).copyTo(dst(roi));
-                }
-            }
-            dst.copyTo(sized);
-        }
-
-        if (gaussian_noise) {
-            cv::Mat noise = cv::Mat(sized.size(), sized.type());
-            gaussian_noise = std::min(gaussian_noise, 127);
-            gaussian_noise = std::max(gaussian_noise, 0);
-            cv::randn(noise, 0, gaussian_noise);  //mean and variance
-            cv::Mat sized_norm = sized + noise;
-            //cv::normalize(sized_norm, sized_norm, 0.0, 255.0, cv::NORM_MINMAX, sized.type());
-            //cv::imshow("source", sized);
-            //cv::imshow("gaussian noise", sized_norm);
-            //cv::waitKey(0);
-            sized = sized_norm;
-        }
-
-        //char txt[100];
-        //sprintf(txt, "blur = %d", blur);
-        //cv::putText(sized, txt, cv::Point(100, 100), cv::FONT_HERSHEY_COMPLEX_SMALL, 1.7, CV_RGB(255, 0, 0), 1, CV_AA);
-
-        // Mat -> image
-        out = mat_to_image(sized);
-    }
-    catch (...) {
-        cerr << "OpenCV can't augment image: " << w << " x " << h << " \n";
-        out = mat_to_image(*(cv::Mat*)mat);
-    }
-    return out;
-}
-
-// blend two images with (alpha and beta)
-extern "C" void blend_images_cv(image new_img, float alpha, image old_img, float beta)
-{
-    cv::Mat new_mat(cv::Size(new_img.w, new_img.h), CV_32FC(new_img.c), new_img.data);// , size_t step = AUTO_STEP)
-    cv::Mat old_mat(cv::Size(old_img.w, old_img.h), CV_32FC(old_img.c), old_img.data);
-    cv::addWeighted(new_mat, alpha, old_mat, beta, 0.0, new_mat);
-}
-
-// bilateralFilter bluring
-extern "C" image blur_image(image src_img, int ksize)
-{
-    cv::Mat src = image_to_mat(src_img);
-    cv::Mat dst;
-    cv::Size kernel_size = cv::Size(ksize, ksize);
-    cv::GaussianBlur(src, dst, kernel_size, 0);
-    //cv::bilateralFilter(src, dst, ksize, 75, 75);
-    image dst_img = mat_to_image(dst);
-    return dst_img;
-}
-
-// ====================================================================
-// Draw object - adversarial attack dnn
-// ====================================================================
-
-std::atomic<int> x_start, y_start;
-std::atomic<int> x_end, y_end;
-std::atomic<int> x_size, y_size;
-std::atomic<bool> draw_select, selected;
-
-void callback_mouse_click(int event, int x, int y, int flags, void* user_data)
-{
-    if (event == cv::EVENT_LBUTTONDOWN)
-    {
-        draw_select = true;
-        selected = false;
-        x_start = x;
-        y_start = y;
-
-        //if (prev_img_rect.contains(Point2i(x, y))) add_id_img = -1;
-        //else if (next_img_rect.contains(Point2i(x, y))) add_id_img = 1;
-        //else add_id_img = 0;
-        //std::cout << "cv::EVENT_LBUTTONDOWN \n";
-    }
-    else if (event == cv::EVENT_LBUTTONUP)
-    {
-        x_size = abs(x - x_start);
-        y_size = abs(y - y_start);
-        x_end = std::max(x, 0);
-        y_end = std::max(y, 0);
-        draw_select = false;
-        selected = true;
-        //std::cout << "cv::EVENT_LBUTTONUP \n";
-    }
-    else if (event == cv::EVENT_MOUSEMOVE)
-    {
-        x_size = abs(x - x_start);
-        y_size = abs(y - y_start);
-        x_end = std::max(x, 0);
-        y_end = std::max(y, 0);
-    }
-}
-
-extern "C" void cv_draw_object(image sized, float *truth_cpu, int max_boxes, int num_truth, int *it_num_set, float *lr_set, int *boxonly, int classes, char **names)
-{
-    cv::Mat frame = image_to_mat(sized);
-    if(frame.channels() == 3) cv::cvtColor(frame, frame, cv::COLOR_RGB2BGR);
-    cv::Mat frame_clone = frame.clone();
-
-
-    std::string const window_name = "Marking image";
-    cv::namedWindow(window_name, cv::WINDOW_NORMAL);
-    cv::resizeWindow(window_name, 1280, 720);
-    cv::imshow(window_name, frame);
-    cv::moveWindow(window_name, 0, 0);
-    cv::setMouseCallback(window_name, callback_mouse_click);
-
-
-    int it_trackbar_value = 200;
-    std::string const it_trackbar_name = "iterations";
-    int it_tb_res = cv::createTrackbar(it_trackbar_name, window_name, &it_trackbar_value, 1000);
-
-    int lr_trackbar_value = 10;
-    std::string const lr_trackbar_name = "learning_rate exp";
-    int lr_tb_res = cv::createTrackbar(lr_trackbar_name, window_name, &lr_trackbar_value, 20);
-
-    int cl_trackbar_value = 0;
-    std::string const cl_trackbar_name = "class_id";
-    int cl_tb_res = cv::createTrackbar(cl_trackbar_name, window_name, &cl_trackbar_value, classes-1);
-
-    std::string const bo_trackbar_name = "box-only";
-    int bo_tb_res = cv::createTrackbar(bo_trackbar_name, window_name, boxonly, 1);
-
-    int i = 0;
-
-    while (!selected) {
-#ifndef CV_VERSION_EPOCH
-        int pressed_key = cv::waitKeyEx(20);	// OpenCV 3.x
-#else
-        int pressed_key = cv::waitKey(20);		// OpenCV 2.x
-#endif
-        if (pressed_key == 27 || pressed_key == 1048603) break;// break;  // ESC - save & exit
-
-        frame_clone = frame.clone();
-        char buff[100];
-        std::string lr_value = "learning_rate = " + std::to_string(1.0 / pow(2, lr_trackbar_value));
-        cv::putText(frame_clone, lr_value, cv::Point2i(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(10, 50, 10), 3);
-        cv::putText(frame_clone, lr_value, cv::Point2i(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(20, 120, 60), 2);
-        cv::putText(frame_clone, lr_value, cv::Point2i(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(50, 200, 100), 1);
-
-        if (names) {
-            std::string obj_name = names[cl_trackbar_value];
-            cv::putText(frame_clone, obj_name, cv::Point2i(10, 40), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(10, 50, 10), 3);
-            cv::putText(frame_clone, obj_name, cv::Point2i(10, 40), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(20, 120, 60), 2);
-            cv::putText(frame_clone, obj_name, cv::Point2i(10, 40), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(50, 200, 100), 1);
-        }
-
-        if (draw_select) {
-             cv::Rect selected_rect(
-                cv::Point2i((int)min(x_start, x_end), (int)min(y_start, y_end)),
-                cv::Size(x_size, y_size));
-
-            rectangle(frame_clone, selected_rect, cv::Scalar(150, 200, 150));
-        }
-
-
-        cv::imshow(window_name, frame_clone);
-    }
-
-    if (selected) {
-        cv::Rect selected_rect(
-            cv::Point2i((int)min(x_start, x_end), (int)min(y_start, y_end)),
-            cv::Size(x_size, y_size));
-
-        printf(" x_start = %d, y_start = %d, x_size = %d, y_size = %d \n",
-            x_start.load(), y_start.load(), x_size.load(), y_size.load());
-
-        rectangle(frame, selected_rect, cv::Scalar(150, 200, 150));
-        cv::imshow(window_name, frame);
-        cv::waitKey(100);
-
-        float width = x_end - x_start;
-        float height = y_end - y_start;
-
-        float const relative_center_x = (float)(x_start + width / 2) / frame.cols;
-        float const relative_center_y = (float)(y_start + height / 2) / frame.rows;
-        float const relative_width = (float)width / frame.cols;
-        float const relative_height = (float)height / frame.rows;
-
-        truth_cpu[i * 5 + 0] = relative_center_x;
-        truth_cpu[i * 5 + 1] = relative_center_y;
-        truth_cpu[i * 5 + 2] = relative_width;
-        truth_cpu[i * 5 + 3] = relative_height;
-        truth_cpu[i * 5 + 4] = cl_trackbar_value;
-    }
-
-    *it_num_set = it_trackbar_value;
-    *lr_set = 1.0 / pow(2, lr_trackbar_value);
-}
-
-// ====================================================================
-// Show Anchors
-// ====================================================================
-extern "C" void show_acnhors(int number_of_boxes, int num_of_clusters, float *rel_width_height_array, model anchors_data, int width, int height)
-{
-    cv::Mat labels = cv::Mat(number_of_boxes, 1, CV_32SC1);
-    cv::Mat points = cv::Mat(number_of_boxes, 2, CV_32FC1);
-    cv::Mat centers = cv::Mat(num_of_clusters, 2, CV_32FC1);
-
-    for (int i = 0; i < number_of_boxes; ++i) {
-        points.at<float>(i, 0) = rel_width_height_array[i * 2];
-        points.at<float>(i, 1) = rel_width_height_array[i * 2 + 1];
-    }
-
-    for (int i = 0; i < num_of_clusters; ++i) {
-        centers.at<float>(i, 0) = anchors_data.centers.vals[i][0];
-        centers.at<float>(i, 1) = anchors_data.centers.vals[i][1];
-    }
-
-    for (int i = 0; i < number_of_boxes; ++i) {
-        labels.at<int>(i, 0) = anchors_data.assignments[i];
-    }
-
-    size_t img_size = 700;
-    cv::Mat img = cv::Mat(img_size, img_size, CV_8UC3);
-
-    for (int i = 0; i < number_of_boxes; ++i) {
-        cv::Point pt;
-        pt.x = points.at<float>(i, 0) * img_size / width;
-        pt.y = points.at<float>(i, 1) * img_size / height;
-        int cluster_idx = labels.at<int>(i, 0);
-        int red_id = (cluster_idx * (uint64_t)123 + 55) % 255;
-        int green_id = (cluster_idx * (uint64_t)321 + 33) % 255;
-        int blue_id = (cluster_idx * (uint64_t)11 + 99) % 255;
-        cv::circle(img, pt, 1, CV_RGB(red_id, green_id, blue_id), CV_FILLED, 8, 0);
-        //if(pt.x > img_size || pt.y > img_size) printf("\n pt.x = %d, pt.y = %d \n", pt.x, pt.y);
-    }
-
-    for (int j = 0; j < num_of_clusters; ++j) {
-        cv::Point pt1, pt2;
-        pt1.x = pt1.y = 0;
-        pt2.x = centers.at<float>(j, 0) * img_size / width;
-        pt2.y = centers.at<float>(j, 1) * img_size / height;
-        cv::rectangle(img, pt1, pt2, CV_RGB(255, 255, 255), 1, 8, 0);
-    }
-    save_mat_png(img, "cloud.png");
-    cv::imshow("clusters", img);
-    cv::waitKey(0);
-    cv::destroyAllWindows();
-}
-
-void show_opencv_info()
-{
-    std::cerr << " OpenCV version: " << CV_VERSION_MAJOR << "." << CV_VERSION_MINOR << "." << CVAUX_STR(CV_VERSION_REVISION) OCV_D
-        << std::endl;
-}
-
-
-
-}   // extern "C"
-#else  // OPENCV
-extern "C" void show_opencv_info()
-{
-    std::cerr << " OpenCV isn't used - data augmentation will be slow \n";
-}
-extern "C" int wait_key_cv(int delay) { return 0; }
-extern "C" int wait_until_press_key_cv() { return 0; }
-extern "C" void destroy_all_windows_cv() {}
-#endif // OPENCV
+#include "image_opencv.h"
+#include <iostream>
+
+#ifdef OPENCV
+#include "utils.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+#include <string>
+#include <vector>
+#include <fstream>
+#include <algorithm>
+#include <atomic>
+
+#include <opencv2/core/version.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/opencv.hpp>
+#include <opencv2/opencv_modules.hpp>
+
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/video/video.hpp>
+
+// includes for OpenCV >= 3.x
+#ifndef CV_VERSION_EPOCH
+#include <opencv2/core/types.hpp>
+#include <opencv2/videoio/videoio.hpp>
+#include <opencv2/imgcodecs/imgcodecs.hpp>
+#endif
+
+// OpenCV includes for OpenCV 2.x
+#ifdef CV_VERSION_EPOCH
+#include <opencv2/highgui/highgui_c.h>
+#include <opencv2/imgproc/imgproc_c.h>
+#include <opencv2/core/types_c.h>
+#include <opencv2/core/version.hpp>
+#endif
+
+//using namespace cv;
+
+using std::cerr;
+using std::endl;
+
+#ifdef DEBUG
+#define OCV_D "d"
+#else
+#define OCV_D
+#endif//DEBUG
+
+
+// OpenCV libraries
+#ifndef CV_VERSION_EPOCH
+#define OPENCV_VERSION CVAUX_STR(CV_VERSION_MAJOR)"" CVAUX_STR(CV_VERSION_MINOR)"" CVAUX_STR(CV_VERSION_REVISION) OCV_D
+#ifndef USE_CMAKE_LIBS
+#pragma comment(lib, "opencv_world" OPENCV_VERSION ".lib")
+#endif    // USE_CMAKE_LIBS
+#else   // CV_VERSION_EPOCH
+#define OPENCV_VERSION CVAUX_STR(CV_VERSION_EPOCH)"" CVAUX_STR(CV_VERSION_MAJOR)"" CVAUX_STR(CV_VERSION_MINOR) OCV_D
+#ifndef USE_CMAKE_LIBS
+#pragma comment(lib, "opencv_core" OPENCV_VERSION ".lib")
+#pragma comment(lib, "opencv_imgproc" OPENCV_VERSION ".lib")
+#pragma comment(lib, "opencv_highgui" OPENCV_VERSION ".lib")
+#endif    // USE_CMAKE_LIBS
+#endif    // CV_VERSION_EPOCH
+
+#include "http_stream.h"
+
+#ifndef CV_RGB
+#define CV_RGB(r, g, b) cvScalar( (b), (g), (r), 0 )
+#endif
+
+#ifndef CV_FILLED
+#define CV_FILLED cv::FILLED
+#endif
+
+#ifndef CV_AA
+#define CV_AA cv::LINE_AA
+#endif
+
+extern "C" {
+
+    //struct mat_cv : cv::Mat {  };
+    //struct cap_cv : cv::VideoCapture { };
+    //struct write_cv : cv::VideoWriter {  };
+
+    //struct mat_cv : cv::Mat { int a[0]; };
+    //struct cap_cv : cv::VideoCapture { int a[0]; };
+    //struct write_cv : cv::VideoWriter { int a[0]; };
+
+// ====================================================================
+// cv::Mat
+// ====================================================================
+    image mat_to_image(cv::Mat mat);
+    cv::Mat image_to_mat(image img);
+//    image ipl_to_image(mat_cv* src);
+//    mat_cv *image_to_ipl(image img);
+//    cv::Mat ipl_to_mat(IplImage *ipl);
+//    IplImage *mat_to_ipl(cv::Mat mat);
+
+
+extern "C" mat_cv *load_image_mat_cv(const char *filename, int flag)
+{
+    cv::Mat *mat_ptr = NULL;
+    try {
+        cv::Mat mat = cv::imread(filename, flag);
+        if (mat.empty())
+        {
+            std::string shrinked_filename = filename;
+            if (shrinked_filename.length() > 1024) {
+                shrinked_filename.resize(1024);
+                shrinked_filename = std::string("name is too long: ") + shrinked_filename;
+            }
+            cerr << "Cannot load image " << shrinked_filename << std::endl;
+            std::ofstream bad_list("bad.list", std::ios::out | std::ios::app);
+            bad_list << shrinked_filename << std::endl;
+            //if (check_mistakes) getchar();
+            return NULL;
+        }
+        cv::Mat dst;
+        if (mat.channels() == 3) cv::cvtColor(mat, dst, cv::COLOR_RGB2BGR);
+        else if (mat.channels() == 4) cv::cvtColor(mat, dst, cv::COLOR_RGBA2BGRA);
+        else dst = mat;
+
+        mat_ptr = new cv::Mat(dst);
+
+        return (mat_cv *)mat_ptr;
+    }
+    catch (...) {
+        cerr << "OpenCV exception: load_image_mat_cv \n";
+    }
+    if (mat_ptr) delete mat_ptr;
+    return NULL;
+}
+// ----------------------------------------
+
+cv::Mat load_image_mat(char *filename, int channels)
+{
+    int flag = cv::IMREAD_UNCHANGED;
+    if (channels == 0) flag = cv::IMREAD_COLOR;
+    else if (channels == 1) flag = cv::IMREAD_GRAYSCALE;
+    else if (channels == 3) flag = cv::IMREAD_COLOR;
+    else {
+        fprintf(stderr, "OpenCV can't force load with %d channels\n", channels);
+    }
+    //flag |= IMREAD_IGNORE_ORIENTATION;    // un-comment it if you want
+
+    cv::Mat *mat_ptr = (cv::Mat *)load_image_mat_cv(filename, flag);
+
+    if (mat_ptr == NULL) {
+        return cv::Mat();
+    }
+    cv::Mat mat = *mat_ptr;
+    delete mat_ptr;
+
+    return mat;
+}
+// ----------------------------------------
+
+extern "C" image load_image_cv(char *filename, int channels)
+{
+    cv::Mat mat = load_image_mat(filename, channels);
+
+    if (mat.empty()) {
+        return make_image(10, 10, channels);
+    }
+    return mat_to_image(mat);
+}
+// ----------------------------------------
+
+extern "C" image load_image_resize(char *filename, int w, int h, int c, image *im)
+{
+    image out;
+    try {
+        cv::Mat loaded_image = load_image_mat(filename, c);
+
+        *im = mat_to_image(loaded_image);
+
+        cv::Mat resized(h, w, CV_8UC3);
+        cv::resize(loaded_image, resized, cv::Size(w, h), 0, 0, cv::INTER_LINEAR);
+        out = mat_to_image(resized);
+    }
+    catch (...) {
+        cerr << " OpenCV exception: load_image_resize() can't load image %s " << filename << " \n";
+        out = make_image(w, h, c);
+        *im = make_image(w, h, c);
+    }
+    return out;
+}
+// ----------------------------------------
+
+extern "C" int get_width_mat(mat_cv *mat)
+{
+    if (mat == NULL) {
+        cerr << " Pointer is NULL in get_width_mat() \n";
+        return 0;
+    }
+    return ((cv::Mat *)mat)->cols;
+}
+// ----------------------------------------
+
+extern "C" int get_height_mat(mat_cv *mat)
+{
+    if (mat == NULL) {
+        cerr << " Pointer is NULL in get_height_mat() \n";
+        return 0;
+    }
+    return ((cv::Mat *)mat)->rows;
+}
+// ----------------------------------------
+
+extern "C" void release_mat(mat_cv **mat)
+{
+    try {
+        cv::Mat **mat_ptr = (cv::Mat **)mat;
+        if (*mat_ptr) delete *mat_ptr;
+        *mat_ptr = NULL;
+    }
+    catch (...) {
+        cerr << "OpenCV exception: release_mat \n";
+    }
+}
+
+// ====================================================================
+// IplImage
+// ====================================================================
+/*
+extern "C" int get_width_cv(mat_cv *ipl_src)
+{
+    IplImage *ipl = (IplImage *)ipl_src;
+    return ipl->width;
+}
+// ----------------------------------------
+
+extern "C" int get_height_cv(mat_cv *ipl_src)
+{
+    IplImage *ipl = (IplImage *)ipl_src;
+    return ipl->height;
+}
+// ----------------------------------------
+
+extern "C" void release_ipl(mat_cv **ipl)
+{
+    IplImage **ipl_img = (IplImage **)ipl;
+    if (*ipl_img) cvReleaseImage(ipl_img);
+    *ipl_img = NULL;
+}
+// ----------------------------------------
+
+// ====================================================================
+// image-to-ipl, ipl-to-image, image_to_mat, mat_to_image
+// ====================================================================
+
+extern "C" mat_cv *image_to_ipl(image im)
+{
+    int x, y, c;
+    IplImage *disp = cvCreateImage(cvSize(im.w, im.h), IPL_DEPTH_8U, im.c);
+    int step = disp->widthStep;
+    for (y = 0; y < im.h; ++y) {
+        for (x = 0; x < im.w; ++x) {
+            for (c = 0; c < im.c; ++c) {
+                float val = im.data[c*im.h*im.w + y*im.w + x];
+                disp->imageData[y*step + x*im.c + c] = (unsigned char)(val * 255);
+            }
+        }
+    }
+    return (mat_cv *)disp;
+}
+// ----------------------------------------
+
+extern "C" image ipl_to_image(mat_cv* src_ptr)
+{
+    IplImage* src = (IplImage*)src_ptr;
+    int h = src->height;
+    int w = src->width;
+    int c = src->nChannels;
+    image im = make_image(w, h, c);
+    unsigned char *data = (unsigned char *)src->imageData;
+    int step = src->widthStep;
+    int i, j, k;
+
+    for (i = 0; i < h; ++i) {
+        for (k = 0; k < c; ++k) {
+            for (j = 0; j < w; ++j) {
+                im.data[k*w*h + i*w + j] = data[i*step + j*c + k] / 255.;
+            }
+        }
+    }
+    return im;
+}
+// ----------------------------------------
+
+cv::Mat ipl_to_mat(IplImage *ipl)
+{
+    Mat m = cvarrToMat(ipl, true);
+    return m;
+}
+// ----------------------------------------
+
+IplImage *mat_to_ipl(cv::Mat mat)
+{
+    IplImage *ipl = new IplImage;
+    *ipl = mat;
+    return ipl;
+}
+// ----------------------------------------
+*/
+
+extern "C" cv::Mat image_to_mat(image img)
+{
+    int channels = img.c;
+    int width = img.w;
+    int height = img.h;
+    cv::Mat mat = cv::Mat(height, width, CV_8UC(channels));
+    int step = mat.step;
+
+    for (int y = 0; y < img.h; ++y) {
+        for (int x = 0; x < img.w; ++x) {
+            for (int c = 0; c < img.c; ++c) {
+                float val = img.data[c*img.h*img.w + y*img.w + x];
+                mat.data[y*step + x*img.c + c] = (unsigned char)(val * 255);
+            }
+        }
+    }
+    return mat;
+}
+// ----------------------------------------
+
+extern "C" image mat_to_image(cv::Mat mat)
+{
+    int w = mat.cols;
+    int h = mat.rows;
+    int c = mat.channels();
+    image im = make_image(w, h, c);
+    unsigned char *data = (unsigned char *)mat.data;
+    int step = mat.step;
+    for (int y = 0; y < h; ++y) {
+        for (int k = 0; k < c; ++k) {
+            for (int x = 0; x < w; ++x) {
+                //uint8_t val = mat.ptr<uint8_t>(y)[c * x + k];
+                //uint8_t val = mat.at<Vec3b>(y, x).val[k];
+                //im.data[k*w*h + y*w + x] = val / 255.0f;
+
+                im.data[k*w*h + y*w + x] = data[y*step + x*c + k] / 255.0f;
+            }
+        }
+    }
+    return im;
+}
+
+image mat_to_image_cv(mat_cv *mat)
+{
+    return mat_to_image(*(cv::Mat*)mat);
+}
+
+// ====================================================================
+// Window
+// ====================================================================
+extern "C" void create_window_cv(char const* window_name, int full_screen, int width, int height)
+{
+    try {
+        int window_type = cv::WINDOW_NORMAL;
+#ifdef CV_VERSION_EPOCH // OpenCV 2.x
+        if (full_screen) window_type = CV_WINDOW_FULLSCREEN;
+#else
+        if (full_screen) window_type = cv::WINDOW_FULLSCREEN;
+#endif
+        cv::namedWindow(window_name, window_type);
+        cv::moveWindow(window_name, 0, 0);
+        cv::resizeWindow(window_name, width, height);
+    }
+    catch (...) {
+        cerr << "OpenCV exception: create_window_cv \n";
+    }
+}
+// ----------------------------------------
+
+extern "C" void resize_window_cv(char const* window_name, int width, int height)
+{
+    try {
+        cv::resizeWindow(window_name, width, height);
+    }
+    catch (...) {
+        cerr << "OpenCV exception: create_window_cv \n";
+    }
+}
+// ----------------------------------------
+
+extern "C" void destroy_all_windows_cv()
+{
+    try {
+        cv::destroyAllWindows();
+    }
+    catch (...) {
+        cerr << "OpenCV exception: destroy_all_windows_cv \n";
+    }
+}
+// ----------------------------------------
+
+extern "C" int wait_key_cv(int delay)
+{
+    try {
+        return cv::waitKey(delay);
+    }
+    catch (...) {
+        cerr << "OpenCV exception: wait_key_cv \n";
+    }
+    return -1;
+}
+// ----------------------------------------
+
+extern "C" int wait_until_press_key_cv()
+{
+    return wait_key_cv(0);
+}
+// ----------------------------------------
+
+extern "C" void make_window(char *name, int w, int h, int fullscreen)
+{
+    try {
+        cv::namedWindow(name, cv::WINDOW_NORMAL);
+        if (fullscreen) {
+#ifdef CV_VERSION_EPOCH // OpenCV 2.x
+            cv::setWindowProperty(name, cv::WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
+#else
+            cv::setWindowProperty(name, cv::WND_PROP_FULLSCREEN, cv::WINDOW_FULLSCREEN);
+#endif
+        }
+        else {
+            cv::resizeWindow(name, w, h);
+            if (strcmp(name, "Demo") == 0) cv::moveWindow(name, 0, 0);
+        }
+    }
+    catch (...) {
+        cerr << "OpenCV exception: make_window \n";
+    }
+}
+// ----------------------------------------
+
+static float get_pixel(image m, int x, int y, int c)
+{
+    assert(x < m.w && y < m.h && c < m.c);
+    return m.data[c*m.h*m.w + y*m.w + x];
+}
+// ----------------------------------------
+
+extern "C" void show_image_cv(image p, const char *name)
+{
+    try {
+        image copy = copy_image(p);
+        constrain_image(copy);
+
+        cv::Mat mat = image_to_mat(copy);
+        if (mat.channels() == 3) cv::cvtColor(mat, mat, cv::COLOR_RGB2BGR);
+        else if (mat.channels() == 4) cv::cvtColor(mat, mat, cv::COLOR_RGBA2BGR);
+        cv::namedWindow(name, cv::WINDOW_NORMAL);
+        cv::imshow(name, mat);
+        free_image(copy);
+    }
+    catch (...) {
+        cerr << "OpenCV exception: show_image_cv \n";
+    }
+}
+// ----------------------------------------
+
+/*
+extern "C" void show_image_cv_ipl(mat_cv *disp, const char *name)
+{
+    if (disp == NULL) return;
+    char buff[256];
+    sprintf(buff, "%s", name);
+    cv::namedWindow(buff, WINDOW_NORMAL);
+    cvShowImage(buff, disp);
+}
+// ----------------------------------------
+*/
+
+extern "C" void show_image_mat(mat_cv *mat_ptr, const char *name)
+{
+    try {
+        if (mat_ptr == NULL) return;
+        cv::Mat &mat = *(cv::Mat *)mat_ptr;
+        cv::namedWindow(name, cv::WINDOW_NORMAL);
+        cv::imshow(name, mat);
+    }
+    catch (...) {
+        cerr << "OpenCV exception: show_image_mat \n";
+    }
+}
+
+// ====================================================================
+// Video Writer
+// ====================================================================
+extern "C" write_cv *create_video_writer(char *out_filename, char c1, char c2, char c3, char c4, int fps, int width, int height, int is_color)
+{
+    try {
+    cv::VideoWriter * output_video_writer =
+#ifdef CV_VERSION_EPOCH
+        new cv::VideoWriter(out_filename, CV_FOURCC(c1, c2, c3, c4), fps, cv::Size(width, height), is_color);
+#else
+        new cv::VideoWriter(out_filename, cv::VideoWriter::fourcc(c1, c2, c3, c4), fps, cv::Size(width, height), is_color);
+#endif
+
+    return (write_cv *)output_video_writer;
+    }
+    catch (...) {
+        cerr << "OpenCV exception: create_video_writer \n";
+    }
+    return NULL;
+}
+
+extern "C" void write_frame_cv(write_cv *output_video_writer, mat_cv *mat)
+{
+    try {
+        cv::VideoWriter *out = (cv::VideoWriter *)output_video_writer;
+        out->write(*(cv::Mat*)mat);
+    }
+    catch (...) {
+        cerr << "OpenCV exception: write_frame_cv \n";
+    }
+}
+
+extern "C" void release_video_writer(write_cv **output_video_writer)
+{
+    try {
+        if (output_video_writer) {
+            std::cout << " closing...";
+            cv::VideoWriter *out = *(cv::VideoWriter **)output_video_writer;
+            out->release();
+            delete out;
+            output_video_writer = NULL;
+            std::cout << " closed!";
+        }
+        else {
+            cerr << "OpenCV exception: output_video_writer isn't created \n";
+        }
+    }
+    catch (...) {
+        cerr << "OpenCV exception: release_video_writer \n";
+    }
+}
+
+/*
+extern "C" void *open_video_stream(const char *f, int c, int w, int h, int fps)
+{
+    VideoCapture *cap;
+    if(f) cap = new VideoCapture(f);
+    else cap = new VideoCapture(c);
+    if(!cap->isOpened()) return 0;
+    if(w) cap->set(CV_CAP_PROP_FRAME_WIDTH, w);
+    if(h) cap->set(CV_CAP_PROP_FRAME_HEIGHT, w);
+    if(fps) cap->set(CV_CAP_PROP_FPS, w);
+    return (void *) cap;
+}
+
+
+extern "C" image get_image_from_stream(void *p)
+{
+    VideoCapture *cap = (VideoCapture *)p;
+    Mat m;
+    *cap >> m;
+    if(m.empty()) return make_empty_image(0,0,0);
+    return mat_to_image(m);
+}
+
+extern "C" int show_image_cv(image im, const char* name, int ms)
+{
+    Mat m = image_to_mat(im);
+    imshow(name, m);
+    int c = waitKey(ms);
+    if (c != -1) c = c%256;
+    return c;
+}
+*/
+
+
+// ====================================================================
+// Video Capture
+// ====================================================================
+
+extern "C" cap_cv* get_capture_video_stream(const char *path) {
+    cv::VideoCapture* cap = NULL;
+    try {
+        cap = new cv::VideoCapture(path);
+    }
+    catch (...) {
+        cerr << " OpenCV exception: video-stream " << path << " can't be opened! \n";
+    }
+    return (cap_cv*)cap;
+}
+// ----------------------------------------
+
+extern "C" cap_cv* get_capture_webcam(int index)
+{
+    cv::VideoCapture* cap = NULL;
+    try {
+        cap = new cv::VideoCapture(index);
+        //cap->set(CV_CAP_PROP_FRAME_WIDTH, 1280);
+        //cap->set(CV_CAP_PROP_FRAME_HEIGHT, 960);
+    }
+    catch (...) {
+        cerr << " OpenCV exception: Web-camera " << index << " can't be opened! \n";
+    }
+    return (cap_cv*)cap;
+}
+// ----------------------------------------
+
+extern "C" void release_capture(cap_cv* cap)
+{
+    try {
+        cv::VideoCapture *cpp_cap = (cv::VideoCapture *)cap;
+        delete cpp_cap;
+    }
+    catch (...) {
+        cerr << " OpenCV exception: cv::VideoCapture " << cap << " can't be released! \n";
+    }
+}
+// ----------------------------------------
+
+extern "C" mat_cv* get_capture_frame_cv(cap_cv *cap) {
+    cv::Mat *mat = NULL;
+    try {
+        mat = new cv::Mat();
+        if (cap) {
+            cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
+            if (cpp_cap.isOpened())
+            {
+                cpp_cap >> *mat;
+            }
+            else std::cout << " Video-stream stopped! \n";
+        }
+        else cerr << " cv::VideoCapture isn't created \n";
+    }
+    catch (...) {
+        std::cout << " OpenCV exception: Video-stream stoped! \n";
+    }
+    return (mat_cv *)mat;
+}
+// ----------------------------------------
+
+extern "C" int get_stream_fps_cpp_cv(cap_cv *cap)
+{
+    int fps = 25;
+    try {
+        cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
+#ifndef CV_VERSION_EPOCH    // OpenCV 3.x
+        fps = cpp_cap.get(cv::CAP_PROP_FPS);
+#else                        // OpenCV 2.x
+        fps = cpp_cap.get(CV_CAP_PROP_FPS);
+#endif
+    }
+    catch (...) {
+        cerr << " Can't get FPS of source videofile. For output video FPS = 25 by default. \n";
+    }
+    return fps;
+}
+// ----------------------------------------
+
+extern "C" double get_capture_property_cv(cap_cv *cap, int property_id)
+{
+    try {
+        cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
+        return cpp_cap.get(property_id);
+    }
+    catch (...) {
+        cerr << " OpenCV exception: Can't get property of source video-stream. \n";
+    }
+    return 0;
+}
+// ----------------------------------------
+
+extern "C" double get_capture_frame_count_cv(cap_cv *cap)
+{
+    try {
+        cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
+#ifndef CV_VERSION_EPOCH    // OpenCV 3.x
+        return cpp_cap.get(cv::CAP_PROP_FRAME_COUNT);
+#else                        // OpenCV 2.x
+        return cpp_cap.get(CV_CAP_PROP_FRAME_COUNT);
+#endif
+    }
+    catch (...) {
+        cerr << " OpenCV exception: Can't get CAP_PROP_FRAME_COUNT of source videofile. \n";
+    }
+    return 0;
+}
+// ----------------------------------------
+
+extern "C" int set_capture_property_cv(cap_cv *cap, int property_id, double value)
+{
+    try {
+        cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
+        return cpp_cap.set(property_id, value);
+    }
+    catch (...) {
+        cerr << " Can't set property of source video-stream. \n";
+    }
+    return false;
+}
+// ----------------------------------------
+
+extern "C" int set_capture_position_frame_cv(cap_cv *cap, int index)
+{
+    try {
+        cv::VideoCapture &cpp_cap = *(cv::VideoCapture *)cap;
+#ifndef CV_VERSION_EPOCH    // OpenCV 3.x
+        return cpp_cap.set(cv::CAP_PROP_POS_FRAMES, index);
+#else                        // OpenCV 2.x
+        return cpp_cap.set(CV_CAP_PROP_POS_FRAMES, index);
+#endif
+    }
+    catch (...) {
+        cerr << " Can't set CAP_PROP_POS_FRAMES of source videofile. \n";
+    }
+    return false;
+}
+// ----------------------------------------
+
+
+
+// ====================================================================
+// ... Video Capture
+// ====================================================================
+
+extern "C" image get_image_from_stream_cpp(cap_cv *cap)
+{
+    cv::Mat *src = NULL;
+    static int once = 1;
+    if (once) {
+        once = 0;
+        do {
+            if (src) delete src;
+            src = (cv::Mat*)get_capture_frame_cv(cap);
+            if (!src) return make_empty_image(0, 0, 0);
+        } while (src->cols < 1 || src->rows < 1 || src->channels() < 1);
+        printf("Video stream: %d x %d \n", src->cols, src->rows);
+    }
+    else
+        src = (cv::Mat*)get_capture_frame_cv(cap);
+
+    if (!src) return make_empty_image(0, 0, 0);
+    image im = mat_to_image(*src);
+    rgbgr_image(im);
+    if (src) delete src;
+    return im;
+}
+// ----------------------------------------
+
+extern "C" int wait_for_stream(cap_cv *cap, cv::Mat* src, int dont_close)
+{
+    if (!src) {
+        if (dont_close) src = new cv::Mat(416, 416, CV_8UC(3)); // cvCreateImage(cvSize(416, 416), IPL_DEPTH_8U, 3);
+        else return 0;
+    }
+    if (src->cols < 1 || src->rows < 1 || src->channels() < 1) {
+        if (dont_close) {
+            delete src;// cvReleaseImage(&src);
+            int z = 0;
+            for (z = 0; z < 20; ++z) {
+                src = (cv::Mat*)get_capture_frame_cv(cap);
+                delete src;// cvReleaseImage(&src);
+            }
+            src = new cv::Mat(416, 416, CV_8UC(3)); // cvCreateImage(cvSize(416, 416), IPL_DEPTH_8U, 3);
+        }
+        else return 0;
+    }
+    return 1;
+}
+// ----------------------------------------
+
+extern "C" image get_image_from_stream_resize(cap_cv *cap, int w, int h, int c, mat_cv** in_img, int dont_close)
+{
+    c = c ? c : 3;
+    cv::Mat *src = NULL;
+
+    static int once = 1;
+    if (once) {
+        once = 0;
+        do {
+            if (src) delete src;
+            src = (cv::Mat*)get_capture_frame_cv(cap);
+            if (!src) return make_empty_image(0, 0, 0);
+        } while (src->cols < 1 || src->rows < 1 || src->channels() < 1);
+        printf("Video stream: %d x %d \n", src->cols, src->rows);
+    }
+    else
+        src = (cv::Mat*)get_capture_frame_cv(cap);
+
+    if (!wait_for_stream(cap, src, dont_close)) return make_empty_image(0, 0, 0);
+
+    *(cv::Mat **)in_img = src;
+
+    cv::Mat new_img = cv::Mat(h, w, CV_8UC(c));
+    cv::resize(*src, new_img, new_img.size(), 0, 0, cv::INTER_LINEAR);
+    if (c>1) cv::cvtColor(new_img, new_img, cv::COLOR_RGB2BGR);
+    image im = mat_to_image(new_img);
+
+    //show_image_cv(im, "im");
+    //show_image_mat(*in_img, "in_img");
+    return im;
+}
+// ----------------------------------------
+
+extern "C" image get_image_from_stream_letterbox(cap_cv *cap, int w, int h, int c, mat_cv** in_img, int dont_close)
+{
+    c = c ? c : 3;
+    cv::Mat *src = NULL;
+    static int once = 1;
+    if (once) {
+        once = 0;
+        do {
+            if (src) delete src;
+            src = (cv::Mat*)get_capture_frame_cv(cap);
+            if (!src) return make_empty_image(0, 0, 0);
+        } while (src->cols < 1 || src->rows < 1 || src->channels() < 1);
+        printf("Video stream: %d x %d \n", src->cols, src->rows);
+    }
+    else
+        src = (cv::Mat*)get_capture_frame_cv(cap);
+
+    if (!wait_for_stream(cap, src, dont_close)) return make_empty_image(0, 0, 0);   // passes (cv::Mat *)src while should be (cv::Mat **)src
+
+    *in_img = (mat_cv *)new cv::Mat(src->rows, src->cols, CV_8UC(c));
+    cv::resize(*src, **(cv::Mat**)in_img, (*(cv::Mat**)in_img)->size(), 0, 0, cv::INTER_LINEAR);
+
+    if (c>1) cv::cvtColor(*src, *src, cv::COLOR_RGB2BGR);
+    image tmp = mat_to_image(*src);
+    image im = letterbox_image(tmp, w, h);
+    free_image(tmp);
+    release_mat((mat_cv **)&src);
+
+    //show_image_cv(im, "im");
+    //show_image_mat(*in_img, "in_img");
+    return im;
+}
+// ----------------------------------------
+
+extern "C" void consume_frame(cap_cv *cap){
+    cv::Mat *src = NULL;
+    src = (cv::Mat *)get_capture_frame_cv(cap);
+    if (src)
+        delete src;
+}
+// ----------------------------------------
+
+
+// ====================================================================
+// Image Saving
+// ====================================================================
+extern int stbi_write_png(char const *filename, int w, int h, int comp, const void  *data, int stride_in_bytes);
+extern int stbi_write_jpg(char const *filename, int x, int y, int comp, const void  *data, int quality);
+
+extern "C" void save_mat_png(cv::Mat img_src, const char *name)
+{
+    cv::Mat img_rgb;
+    if (img_src.channels() >= 3) cv::cvtColor(img_src, img_rgb, cv::COLOR_RGB2BGR);
+    stbi_write_png(name, img_rgb.cols, img_rgb.rows, 3, (char *)img_rgb.data, 0);
+}
+// ----------------------------------------
+
+extern "C" void save_mat_jpg(cv::Mat img_src, const char *name)
+{
+    cv::Mat img_rgb;
+    if (img_src.channels() >= 3) cv::cvtColor(img_src, img_rgb, cv::COLOR_RGB2BGR);
+    stbi_write_jpg(name, img_rgb.cols, img_rgb.rows, 3, (char *)img_rgb.data, 80);
+}
+// ----------------------------------------
+
+
+extern "C" void save_cv_png(mat_cv *img_src, const char *name)
+{
+    cv::Mat* img = (cv::Mat* )img_src;
+    save_mat_png(*img, name);
+}
+// ----------------------------------------
+
+extern "C" void save_cv_jpg(mat_cv *img_src, const char *name)
+{
+    cv::Mat* img = (cv::Mat*)img_src;
+    save_mat_jpg(*img, name);
+}
+// ----------------------------------------
+
+
+// ====================================================================
+// Draw Detection
+// ====================================================================
+extern "C" void draw_detections_cv_v3(mat_cv* mat, detection *dets, int num, float thresh, char **names, image **alphabet, int classes, int ext_output)
+{
+    try {
+        cv::Mat *show_img = (cv::Mat*)mat;
+        int i, j;
+        if (!show_img) return;
+        static int frame_id = 0;
+        frame_id++;
+
+        for (i = 0; i < num; ++i) {
+            char labelstr[4096] = { 0 };
+            int class_id = -1;
+            for (j = 0; j < classes; ++j) {
+                int show = strncmp(names[j], "dont_show", 9);
+                if (dets[i].prob[j] > thresh && show) {
+                    if (class_id < 0) {
+                        strcat(labelstr, names[j]);
+                        class_id = j;
+                        char buff[20];
+                        if (dets[i].track_id) {
+                            sprintf(buff, " (id: %d)", dets[i].track_id);
+                            strcat(labelstr, buff);
+                        }
+                        sprintf(buff, " (%2.0f%%)", dets[i].prob[j] * 100);
+                        strcat(labelstr, buff);
+                        printf("%s: %.0f%% ", names[j], dets[i].prob[j] * 100);
+                        if (dets[i].track_id) printf("(track = %d, sim = %f) ", dets[i].track_id, dets[i].sim);
+                    }
+                    else {
+                        strcat(labelstr, ", ");
+                        strcat(labelstr, names[j]);
+                        printf(", %s: %.0f%% ", names[j], dets[i].prob[j] * 100);
+                    }
+                }
+            }
+            if (class_id >= 0) {
+                int width = std::max(1.0f, show_img->rows * .002f);
+
+                //if(0){
+                //width = pow(prob, 1./2.)*10+1;
+                //alphabet = 0;
+                //}
+
+                //printf("%d %s: %.0f%%\n", i, names[class_id], prob*100);
+                int offset = class_id * 123457 % classes;
+                float red = get_color(2, offset, classes);
+                float green = get_color(1, offset, classes);
+                float blue = get_color(0, offset, classes);
+                float rgb[3];
+
+                //width = prob*20+2;
+
+                rgb[0] = red;
+                rgb[1] = green;
+                rgb[2] = blue;
+                box b = dets[i].bbox;
+                if (std::isnan(b.w) || std::isinf(b.w)) b.w = 0.5;
+                if (std::isnan(b.h) || std::isinf(b.h)) b.h = 0.5;
+                if (std::isnan(b.x) || std::isinf(b.x)) b.x = 0.5;
+                if (std::isnan(b.y) || std::isinf(b.y)) b.y = 0.5;
+                b.w = (b.w < 1) ? b.w : 1;
+                b.h = (b.h < 1) ? b.h : 1;
+                b.x = (b.x < 1) ? b.x : 1;
+                b.y = (b.y < 1) ? b.y : 1;
+                //printf("%f %f %f %f\n", b.x, b.y, b.w, b.h);
+
+                int left = (b.x - b.w / 2.)*show_img->cols;
+                int right = (b.x + b.w / 2.)*show_img->cols;
+                int top = (b.y - b.h / 2.)*show_img->rows;
+                int bot = (b.y + b.h / 2.)*show_img->rows;
+
+                if (left < 0) left = 0;
+                if (right > show_img->cols - 1) right = show_img->cols - 1;
+                if (top < 0) top = 0;
+                if (bot > show_img->rows - 1) bot = show_img->rows - 1;
+
+                //int b_x_center = (left + right) / 2;
+                //int b_y_center = (top + bot) / 2;
+                //int b_width = right - left;
+                //int b_height = bot - top;
+                //sprintf(labelstr, "%d x %d - w: %d, h: %d", b_x_center, b_y_center, b_width, b_height);
+
+                float const font_size = show_img->rows / 1000.F;
+                cv::Size const text_size = cv::getTextSize(labelstr, cv::FONT_HERSHEY_COMPLEX_SMALL, font_size, 1, 0);
+                cv::Point pt1, pt2, pt_text, pt_text_bg1, pt_text_bg2;
+                pt1.x = left;
+                pt1.y = top;
+                pt2.x = right;
+                pt2.y = bot;
+                pt_text.x = left;
+                pt_text.y = top - 4;// 12;
+                pt_text_bg1.x = left;
+                pt_text_bg1.y = top - (3 + 18 * font_size);
+                pt_text_bg2.x = right;
+                if ((right - left) < text_size.width) pt_text_bg2.x = left + text_size.width;
+                pt_text_bg2.y = top;
+                cv::Scalar color;
+                color.val[0] = red * 256;
+                color.val[1] = green * 256;
+                color.val[2] = blue * 256;
+
+                // you should create directory: result_img
+                //static int copied_frame_id = -1;
+                //static IplImage* copy_img = NULL;
+                //if (copied_frame_id != frame_id) {
+                //    copied_frame_id = frame_id;
+                //    if(copy_img == NULL) copy_img = cvCreateImage(cvSize(show_img->width, show_img->height), show_img->depth, show_img->nChannels);
+                //    cvCopy(show_img, copy_img, 0);
+                //}
+                //static int img_id = 0;
+                //img_id++;
+                //char image_name[1024];
+                //sprintf(image_name, "result_img/img_%d_%d_%d_%s.jpg", frame_id, img_id, class_id, names[class_id]);
+                //CvRect rect = cvRect(pt1.x, pt1.y, pt2.x - pt1.x, pt2.y - pt1.y);
+                //cvSetImageROI(copy_img, rect);
+                //cvSaveImage(image_name, copy_img, 0);
+                //cvResetImageROI(copy_img);
+
+                cv::rectangle(*show_img, pt1, pt2, color, width, 8, 0);
+                if (ext_output)
+                    printf("\t(left_x: %4.0f   top_y: %4.0f   width: %4.0f   height: %4.0f)\n",
+                    (float)left, (float)top, b.w*show_img->cols, b.h*show_img->rows);
+                else
+                    printf("\n");
+
+                cv::rectangle(*show_img, pt_text_bg1, pt_text_bg2, color, width, 8, 0);
+                cv::rectangle(*show_img, pt_text_bg1, pt_text_bg2, color, CV_FILLED, 8, 0);    // filled
+                cv::Scalar black_color = CV_RGB(0, 0, 0);
+                cv::putText(*show_img, labelstr, pt_text, cv::FONT_HERSHEY_COMPLEX_SMALL, font_size, black_color, 2 * font_size, CV_AA);
+                // cv::FONT_HERSHEY_COMPLEX_SMALL, cv::FONT_HERSHEY_SIMPLEX
+            }
+        }
+        if (ext_output) {
+            fflush(stdout);
+        }
+    }
+    catch (...) {
+        cerr << "OpenCV exception: draw_detections_cv_v3() \n";
+    }
+}
+// ----------------------------------------
+
+// ====================================================================
+// Draw Loss & Accuracy chart
+// ====================================================================
+extern "C" mat_cv* draw_train_chart(char *windows_name, float max_img_loss, int max_batches, int number_of_lines, int img_size, int dont_show, char* chart_path)
+{
+    int img_offset = 60;
+    int draw_size = img_size - img_offset;
+    cv::Mat *img_ptr = new cv::Mat(img_size, img_size, CV_8UC3, CV_RGB(255, 255, 255));
+    cv::Mat &img = *img_ptr;
+    cv::Point pt1, pt2, pt_text;
+
+    try {
+        // load chart from file
+        if (chart_path != NULL && chart_path[0] != '\0') {
+            *img_ptr = cv::imread(chart_path);
+        }
+        else {
+            // draw new chart
+            char char_buff[100];
+            int i;
+            // vertical lines
+            pt1.x = img_offset; pt2.x = img_size, pt_text.x = 30;
+            for (i = 1; i <= number_of_lines; ++i) {
+                pt1.y = pt2.y = (float)i * draw_size / number_of_lines;
+                cv::line(img, pt1, pt2, CV_RGB(224, 224, 224), 1, 8, 0);
+                if (i % 10 == 0) {
+                    sprintf(char_buff, "%2.1f", max_img_loss*(number_of_lines - i) / number_of_lines);
+                    pt_text.y = pt1.y + 3;
+
+                    cv::putText(img, char_buff, pt_text, cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 0), 1, CV_AA);
+                    cv::line(img, pt1, pt2, CV_RGB(128, 128, 128), 1, 8, 0);
+                }
+            }
+            // horizontal lines
+            pt1.y = draw_size; pt2.y = 0, pt_text.y = draw_size + 15;
+            for (i = 0; i <= number_of_lines; ++i) {
+                pt1.x = pt2.x = img_offset + (float)i * draw_size / number_of_lines;
+                cv::line(img, pt1, pt2, CV_RGB(224, 224, 224), 1, 8, 0);
+                if (i % 10 == 0) {
+                    sprintf(char_buff, "%d", max_batches * i / number_of_lines);
+                    pt_text.x = pt1.x - 20;
+                    cv::putText(img, char_buff, pt_text, cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 0), 1, CV_AA);
+                    cv::line(img, pt1, pt2, CV_RGB(128, 128, 128), 1, 8, 0);
+                }
+            }
+
+            cv::putText(img, "Loss", cv::Point(10, 60), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 255), 1, CV_AA);
+            cv::putText(img, "Iteration number", cv::Point(draw_size / 2, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 0), 1, CV_AA);
+            char max_batches_buff[100];
+            sprintf(max_batches_buff, "in cfg max_batches=%d", max_batches);
+            cv::putText(img, max_batches_buff, cv::Point(draw_size - 195, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 0), 1, CV_AA);
+            cv::putText(img, "Press 's' to save : chart.png", cv::Point(5, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 0), 1, CV_AA);
+        }
+
+        if (!dont_show) {
+            printf(" If error occurs - run training with flag: -dont_show \n");
+            cv::namedWindow(windows_name, cv::WINDOW_NORMAL);
+            cv::moveWindow(windows_name, 0, 0);
+            cv::resizeWindow(windows_name, img_size, img_size);
+            cv::imshow(windows_name, img);
+            cv::waitKey(20);
+        }
+    }
+    catch (...) {
+        cerr << "OpenCV exception: draw_train_chart() \n";
+    }
+    return (mat_cv*)img_ptr;
+}
+// ----------------------------------------
+
+extern "C" void draw_train_loss(char *windows_name, mat_cv* img_src, int img_size, float avg_loss, float max_img_loss, int current_batch, int max_batches,
+    float precision, int draw_precision, char *accuracy_name, float contr_acc, int dont_show, int mjpeg_port, double time_remaining)
+{
+    try {
+        cv::Mat &img = *(cv::Mat*)img_src;
+        int img_offset = 60;
+        int draw_size = img_size - img_offset;
+        char char_buff[100];
+        cv::Point pt1, pt2;
+        pt1.x = img_offset + draw_size * (float)current_batch / max_batches;
+        pt1.y = draw_size * (1 - avg_loss / max_img_loss);
+        if (pt1.y < 0) pt1.y = 1;
+        cv::circle(img, pt1, 1, CV_RGB(0, 0, 255), CV_FILLED, 8, 0);
+
+        // contrastive accuracy
+        if (contr_acc >= 0) {
+            static float old_contr_acc = 0;
+
+            if (current_batch > 0) {
+                cv::line(img,
+                    cv::Point(img_offset + draw_size * (float)(current_batch - 1) / max_batches, draw_size * (1 - old_contr_acc)),
+                    cv::Point(img_offset + draw_size * (float)current_batch / max_batches, draw_size * (1 - contr_acc)),
+                    CV_RGB(0, 150, 70), 1, 8, 0);
+            }
+            old_contr_acc = contr_acc;
+
+            sprintf(char_buff, "C:%2.1f%% ", contr_acc * 100);
+            cv::putText(img, char_buff, cv::Point(1, 45), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 255, 255), 5, CV_AA);
+            cv::putText(img, char_buff, cv::Point(1, 45), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 150, 70), 1, CV_AA);
+        }
+
+        // precision
+        if (draw_precision) {
+            static float old_precision = 0;
+            static float max_precision = 0;
+            static int iteration_old = 0;
+            static int text_iteration_old = 0;
+            if (iteration_old == 0)
+                cv::putText(img, accuracy_name, cv::Point(10, 12), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 0, 0), 1, CV_AA);
+
+	        if (iteration_old != 0){
+            	    cv::line(img,
+                        cv::Point(img_offset + draw_size * (float)iteration_old / max_batches, draw_size * (1 - old_precision)),
+                        cv::Point(img_offset + draw_size * (float)current_batch / max_batches, draw_size * (1 - precision)),
+                        CV_RGB(255, 0, 0), 1, 8, 0);
+	        }
+
+            sprintf(char_buff, "%2.1f%% ", precision * 100);
+            cv::putText(img, char_buff, cv::Point(10, 28), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 255, 255), 5, CV_AA);
+            cv::putText(img, char_buff, cv::Point(10, 28), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(200, 0, 0), 1, CV_AA);
+
+            if ((std::fabs(old_precision - precision) > 0.1)  || (max_precision < precision) || (current_batch - text_iteration_old) >= max_batches / 10) {
+                text_iteration_old = current_batch;
+                max_precision = std::max(max_precision, precision);
+                sprintf(char_buff, "%2.0f%% ", precision * 100);
+                cv::putText(img, char_buff, cv::Point(pt1.x - 30, draw_size * (1 - precision) + 15), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 255, 255), 5, CV_AA);
+                cv::putText(img, char_buff, cv::Point(pt1.x - 30, draw_size * (1 - precision) + 15), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(200, 0, 0), 1, CV_AA);
+            }
+            old_precision = precision;
+            iteration_old = current_batch;
+        }
+        sprintf(char_buff, "current avg loss = %2.4f    iteration = %d    approx. time left = %2.2f hours", avg_loss, current_batch, time_remaining);
+        pt1.x = 15, pt1.y = draw_size + 18;
+        pt2.x = pt1.x + 800, pt2.y = pt1.y + 20;
+        cv::rectangle(img, pt1, pt2, CV_RGB(255, 255, 255), CV_FILLED, 8, 0);
+        pt1.y += 15;
+        cv::putText(img, char_buff, pt1, cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(0, 0, 100), 1, CV_AA);
+
+        int k = 0;
+        if (!dont_show) {
+            cv::imshow(windows_name, img);
+            k = cv::waitKey(20);
+        }
+        static int old_batch = 0;
+        if (k == 's' || current_batch == (max_batches - 1) || (current_batch / 100 > old_batch / 100)) {
+            old_batch = current_batch;
+            save_mat_png(img, "chart.png");
+            save_mat_png(img, windows_name);
+            cv::putText(img, "- Saved", cv::Point(260, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 0, 0), 1, CV_AA);
+        }
+        else
+            cv::putText(img, "- Saved", cv::Point(260, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 255, 255), 1, CV_AA);
+
+        if (mjpeg_port > 0) send_mjpeg((mat_cv *)&img, mjpeg_port, 500000, 70);
+    }
+    catch (...) {
+        cerr << "OpenCV exception: draw_train_loss() \n";
+    }
+}
+// ----------------------------------------
+
+
+// ====================================================================
+// Data augmentation
+// ====================================================================
+
+extern "C" image image_data_augmentation(mat_cv* mat, int w, int h,
+    int pleft, int ptop, int swidth, int sheight, int flip,
+    float dhue, float dsat, float dexp,
+    int gaussian_noise, int blur, int num_boxes, int truth_size, float *truth)
+{
+    image out;
+    try {
+        cv::Mat img = *(cv::Mat *)mat;
+
+        // crop
+        cv::Rect src_rect(pleft, ptop, swidth, sheight);
+        cv::Rect img_rect(cv::Point2i(0, 0), img.size());
+        cv::Rect new_src_rect = src_rect & img_rect;
+
+        cv::Rect dst_rect(cv::Point2i(std::max<int>(0, -pleft), std::max<int>(0, -ptop)), new_src_rect.size());
+        cv::Mat sized;
+
+        if (src_rect.x == 0 && src_rect.y == 0 && src_rect.size() == img.size()) {
+            cv::resize(img, sized, cv::Size(w, h), 0, 0, cv::INTER_LINEAR);
+        }
+        else {
+            cv::Mat cropped(src_rect.size(), img.type());
+            //cropped.setTo(cv::Scalar::all(0));
+            cropped.setTo(cv::mean(img));
+
+            img(new_src_rect).copyTo(cropped(dst_rect));
+
+            // resize
+            cv::resize(cropped, sized, cv::Size(w, h), 0, 0, cv::INTER_LINEAR);
+        }
+
+        // flip
+        if (flip) {
+            cv::Mat cropped;
+            cv::flip(sized, cropped, 1);    // 0 - x-axis, 1 - y-axis, -1 - both axes (x & y)
+            sized = cropped.clone();
+        }
+
+        // HSV augmentation
+        // cv::COLOR_BGR2HSV, cv::COLOR_RGB2HSV, cv::COLOR_HSV2BGR, cv::COLOR_HSV2RGB
+        if (dsat != 1 || dexp != 1 || dhue != 0) {
+            if (img.channels() >= 3)
+            {
+                cv::Mat hsv_src;
+                cvtColor(sized, hsv_src, cv::COLOR_RGB2HSV);    // RGB to HSV
+
+                std::vector<cv::Mat> hsv;
+                cv::split(hsv_src, hsv);
+
+                hsv[1] *= dsat;
+                hsv[2] *= dexp;
+                hsv[0] += 179 * dhue;
+
+                cv::merge(hsv, hsv_src);
+
+                cvtColor(hsv_src, sized, cv::COLOR_HSV2RGB);    // HSV to RGB (the same as previous)
+            }
+            else
+            {
+                sized *= dexp;
+            }
+        }
+
+        //std::stringstream window_name;
+        //window_name << "augmentation - " << ipl;
+        //cv::imshow(window_name.str(), sized);
+        //cv::waitKey(0);
+
+        if (blur) {
+            cv::Mat dst(sized.size(), sized.type());
+            if (blur == 1) {
+                cv::GaussianBlur(sized, dst, cv::Size(17, 17), 0);
+                //cv::bilateralFilter(sized, dst, 17, 75, 75);
+            }
+            else {
+                int ksize = (blur / 2) * 2 + 1;
+                cv::Size kernel_size = cv::Size(ksize, ksize);
+                cv::GaussianBlur(sized, dst, kernel_size, 0);
+                //cv::medianBlur(sized, dst, ksize);
+                //cv::bilateralFilter(sized, dst, ksize, 75, 75);
+
+                // sharpen
+                //cv::Mat img_tmp;
+                //cv::GaussianBlur(dst, img_tmp, cv::Size(), 3);
+                //cv::addWeighted(dst, 1.5, img_tmp, -0.5, 0, img_tmp);
+                //dst = img_tmp;
+            }
+            //std::cout << " blur num_boxes = " << num_boxes << std::endl;
+
+            if (blur == 1) {
+                cv::Rect img_rect(0, 0, sized.cols, sized.rows);
+                int t;
+                for (t = 0; t < num_boxes; ++t) {
+                    box b = float_to_box_stride(truth + t*truth_size, 1);
+                    if (!b.x) break;
+                    int left = (b.x - b.w / 2.)*sized.cols;
+                    int width = b.w*sized.cols;
+                    int top = (b.y - b.h / 2.)*sized.rows;
+                    int height = b.h*sized.rows;
+                    cv::Rect roi(left, top, width, height);
+                    roi = roi & img_rect;
+
+                    sized(roi).copyTo(dst(roi));
+                }
+            }
+            dst.copyTo(sized);
+        }
+
+        if (gaussian_noise) {
+            cv::Mat noise = cv::Mat(sized.size(), sized.type());
+            gaussian_noise = std::min(gaussian_noise, 127);
+            gaussian_noise = std::max(gaussian_noise, 0);
+            cv::randn(noise, 0, gaussian_noise);  //mean and variance
+            cv::Mat sized_norm = sized + noise;
+            //cv::normalize(sized_norm, sized_norm, 0.0, 255.0, cv::NORM_MINMAX, sized.type());
+            //cv::imshow("source", sized);
+            //cv::imshow("gaussian noise", sized_norm);
+            //cv::waitKey(0);
+            sized = sized_norm;
+        }
+
+        //char txt[100];
+        //sprintf(txt, "blur = %d", blur);
+        //cv::putText(sized, txt, cv::Point(100, 100), cv::FONT_HERSHEY_COMPLEX_SMALL, 1.7, CV_RGB(255, 0, 0), 1, CV_AA);
+
+        // Mat -> image
+        out = mat_to_image(sized);
+    }
+    catch (...) {
+        cerr << "OpenCV can't augment image: " << w << " x " << h << " \n";
+        out = mat_to_image(*(cv::Mat*)mat);
+    }
+    return out;
+}
+
+// blend two images with (alpha and beta)
+extern "C" void blend_images_cv(image new_img, float alpha, image old_img, float beta)
+{
+    cv::Mat new_mat(cv::Size(new_img.w, new_img.h), CV_32FC(new_img.c), new_img.data);// , size_t step = AUTO_STEP)
+    cv::Mat old_mat(cv::Size(old_img.w, old_img.h), CV_32FC(old_img.c), old_img.data);
+    cv::addWeighted(new_mat, alpha, old_mat, beta, 0.0, new_mat);
+}
+
+// bilateralFilter bluring
+extern "C" image blur_image(image src_img, int ksize)
+{
+    cv::Mat src = image_to_mat(src_img);
+    cv::Mat dst;
+    cv::Size kernel_size = cv::Size(ksize, ksize);
+    cv::GaussianBlur(src, dst, kernel_size, 0);
+    //cv::bilateralFilter(src, dst, ksize, 75, 75);
+    image dst_img = mat_to_image(dst);
+    return dst_img;
+}
+
+// ====================================================================
+// Draw object - adversarial attack dnn
+// ====================================================================
+
+std::atomic<int> x_start, y_start;
+std::atomic<int> x_end, y_end;
+std::atomic<int> x_size, y_size;
+std::atomic<bool> draw_select, selected;
+
+void callback_mouse_click(int event, int x, int y, int flags, void* user_data)
+{
+    if (event == cv::EVENT_LBUTTONDOWN)
+    {
+        draw_select = true;
+        selected = false;
+        x_start = x;
+        y_start = y;
+
+        //if (prev_img_rect.contains(Point2i(x, y))) add_id_img = -1;
+        //else if (next_img_rect.contains(Point2i(x, y))) add_id_img = 1;
+        //else add_id_img = 0;
+        //std::cout << "cv::EVENT_LBUTTONDOWN \n";
+    }
+    else if (event == cv::EVENT_LBUTTONUP)
+    {
+        x_size = abs(x - x_start);
+        y_size = abs(y - y_start);
+        x_end = std::max(x, 0);
+        y_end = std::max(y, 0);
+        draw_select = false;
+        selected = true;
+        //std::cout << "cv::EVENT_LBUTTONUP \n";
+    }
+    else if (event == cv::EVENT_MOUSEMOVE)
+    {
+        x_size = abs(x - x_start);
+        y_size = abs(y - y_start);
+        x_end = std::max(x, 0);
+        y_end = std::max(y, 0);
+    }
+}
+
+extern "C" void cv_draw_object(image sized, float *truth_cpu, int max_boxes, int num_truth, int *it_num_set, float *lr_set, int *boxonly, int classes, char **names)
+{
+    cv::Mat frame = image_to_mat(sized);
+    if(frame.channels() == 3) cv::cvtColor(frame, frame, cv::COLOR_RGB2BGR);
+    cv::Mat frame_clone = frame.clone();
+
+
+    std::string const window_name = "Marking image";
+    cv::namedWindow(window_name, cv::WINDOW_NORMAL);
+    cv::resizeWindow(window_name, 1280, 720);
+    cv::imshow(window_name, frame);
+    cv::moveWindow(window_name, 0, 0);
+    cv::setMouseCallback(window_name, callback_mouse_click);
+
+
+    int it_trackbar_value = 200;
+    std::string const it_trackbar_name = "iterations";
+    int it_tb_res = cv::createTrackbar(it_trackbar_name, window_name, &it_trackbar_value, 1000);
+
+    int lr_trackbar_value = 10;
+    std::string const lr_trackbar_name = "learning_rate exp";
+    int lr_tb_res = cv::createTrackbar(lr_trackbar_name, window_name, &lr_trackbar_value, 20);
+
+    int cl_trackbar_value = 0;
+    std::string const cl_trackbar_name = "class_id";
+    int cl_tb_res = cv::createTrackbar(cl_trackbar_name, window_name, &cl_trackbar_value, classes-1);
+
+    std::string const bo_trackbar_name = "box-only";
+    int bo_tb_res = cv::createTrackbar(bo_trackbar_name, window_name, boxonly, 1);
+
+    int i = 0;
+
+    while (!selected) {
+#ifndef CV_VERSION_EPOCH
+        int pressed_key = cv::waitKeyEx(20);	// OpenCV 3.x
+#else
+        int pressed_key = cv::waitKey(20);		// OpenCV 2.x
+#endif
+        if (pressed_key == 27 || pressed_key == 1048603) break;// break;  // ESC - save & exit
+
+        frame_clone = frame.clone();
+        char buff[100];
+        std::string lr_value = "learning_rate = " + std::to_string(1.0 / pow(2, lr_trackbar_value));
+        cv::putText(frame_clone, lr_value, cv::Point2i(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(10, 50, 10), 3);
+        cv::putText(frame_clone, lr_value, cv::Point2i(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(20, 120, 60), 2);
+        cv::putText(frame_clone, lr_value, cv::Point2i(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(50, 200, 100), 1);
+
+        if (names) {
+            std::string obj_name = names[cl_trackbar_value];
+            cv::putText(frame_clone, obj_name, cv::Point2i(10, 40), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(10, 50, 10), 3);
+            cv::putText(frame_clone, obj_name, cv::Point2i(10, 40), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(20, 120, 60), 2);
+            cv::putText(frame_clone, obj_name, cv::Point2i(10, 40), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(50, 200, 100), 1);
+        }
+
+        if (draw_select) {
+             cv::Rect selected_rect(
+                cv::Point2i((int)min(x_start, x_end), (int)min(y_start, y_end)),
+                cv::Size(x_size, y_size));
+
+            rectangle(frame_clone, selected_rect, cv::Scalar(150, 200, 150));
+        }
+
+
+        cv::imshow(window_name, frame_clone);
+    }
+
+    if (selected) {
+        cv::Rect selected_rect(
+            cv::Point2i((int)min(x_start, x_end), (int)min(y_start, y_end)),
+            cv::Size(x_size, y_size));
+
+        printf(" x_start = %d, y_start = %d, x_size = %d, y_size = %d \n",
+            x_start.load(), y_start.load(), x_size.load(), y_size.load());
+
+        rectangle(frame, selected_rect, cv::Scalar(150, 200, 150));
+        cv::imshow(window_name, frame);
+        cv::waitKey(100);
+
+        float width = x_end - x_start;
+        float height = y_end - y_start;
+
+        float const relative_center_x = (float)(x_start + width / 2) / frame.cols;
+        float const relative_center_y = (float)(y_start + height / 2) / frame.rows;
+        float const relative_width = (float)width / frame.cols;
+        float const relative_height = (float)height / frame.rows;
+
+        truth_cpu[i * 5 + 0] = relative_center_x;
+        truth_cpu[i * 5 + 1] = relative_center_y;
+        truth_cpu[i * 5 + 2] = relative_width;
+        truth_cpu[i * 5 + 3] = relative_height;
+        truth_cpu[i * 5 + 4] = cl_trackbar_value;
+    }
+
+    *it_num_set = it_trackbar_value;
+    *lr_set = 1.0 / pow(2, lr_trackbar_value);
+}
+
+// ====================================================================
+// Show Anchors
+// ====================================================================
+extern "C" void show_acnhors(int number_of_boxes, int num_of_clusters, float *rel_width_height_array, model anchors_data, int width, int height)
+{
+    cv::Mat labels = cv::Mat(number_of_boxes, 1, CV_32SC1);
+    cv::Mat points = cv::Mat(number_of_boxes, 2, CV_32FC1);
+    cv::Mat centers = cv::Mat(num_of_clusters, 2, CV_32FC1);
+
+    for (int i = 0; i < number_of_boxes; ++i) {
+        points.at<float>(i, 0) = rel_width_height_array[i * 2];
+        points.at<float>(i, 1) = rel_width_height_array[i * 2 + 1];
+    }
+
+    for (int i = 0; i < num_of_clusters; ++i) {
+        centers.at<float>(i, 0) = anchors_data.centers.vals[i][0];
+        centers.at<float>(i, 1) = anchors_data.centers.vals[i][1];
+    }
+
+    for (int i = 0; i < number_of_boxes; ++i) {
+        labels.at<int>(i, 0) = anchors_data.assignments[i];
+    }
+
+    size_t img_size = 700;
+    cv::Mat img = cv::Mat(img_size, img_size, CV_8UC3);
+
+    for (int i = 0; i < number_of_boxes; ++i) {
+        cv::Point pt;
+        pt.x = points.at<float>(i, 0) * img_size / width;
+        pt.y = points.at<float>(i, 1) * img_size / height;
+        int cluster_idx = labels.at<int>(i, 0);
+        int red_id = (cluster_idx * (uint64_t)123 + 55) % 255;
+        int green_id = (cluster_idx * (uint64_t)321 + 33) % 255;
+        int blue_id = (cluster_idx * (uint64_t)11 + 99) % 255;
+        cv::circle(img, pt, 1, CV_RGB(red_id, green_id, blue_id), CV_FILLED, 8, 0);
+        //if(pt.x > img_size || pt.y > img_size) printf("\n pt.x = %d, pt.y = %d \n", pt.x, pt.y);
+    }
+
+    for (int j = 0; j < num_of_clusters; ++j) {
+        cv::Point pt1, pt2;
+        pt1.x = pt1.y = 0;
+        pt2.x = centers.at<float>(j, 0) * img_size / width;
+        pt2.y = centers.at<float>(j, 1) * img_size / height;
+        cv::rectangle(img, pt1, pt2, CV_RGB(255, 255, 255), 1, 8, 0);
+    }
+    save_mat_png(img, "cloud.png");
+    cv::imshow("clusters", img);
+    cv::waitKey(0);
+    cv::destroyAllWindows();
+}
+
+void show_opencv_info()
+{
+    std::cerr << " OpenCV version: " << CV_VERSION_MAJOR << "." << CV_VERSION_MINOR << "." << CVAUX_STR(CV_VERSION_REVISION) OCV_D
+        << std::endl;
+}
+
+
+
+}   // extern "C"
+#else  // OPENCV
+extern "C" void show_opencv_info()
+{
+    std::cerr << " OpenCV isn't used - data augmentation will be slow \n";
+}
+extern "C" int wait_key_cv(int delay) { return 0; }
+extern "C" int wait_until_press_key_cv() { return 0; }
+extern "C" void destroy_all_windows_cv() {}
+extern "C" void resize_window_cv(char const* window_name, int width, int height) {}
+#endif // OPENCV

--
Gitblit v1.8.0