mirror of
https://github.com/opencv/opencv.git
synced 2024-11-27 12:40:05 +08:00
Merge pull request #15492 from TolyaTalamanov:at/new-render-prims
This commit is contained in:
commit
3133bb49aa
@ -48,6 +48,7 @@ set(gapi_srcs
|
||||
src/api/kernels_core.cpp
|
||||
src/api/kernels_imgproc.cpp
|
||||
src/api/render.cpp
|
||||
src/api/render_ocv.cpp
|
||||
src/api/ginfer.cpp
|
||||
|
||||
# Compiler part
|
||||
|
@ -2,7 +2,7 @@
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2018 Intel Corporation
|
||||
// Copyright (C) 2018-2019 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_RENDER_HPP
|
||||
@ -11,6 +11,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <opencv2/gapi.hpp>
|
||||
|
||||
#include <opencv2/gapi/opencv_includes.hpp>
|
||||
#include <opencv2/gapi/util/variant.hpp>
|
||||
#include <opencv2/gapi/own/exports.hpp>
|
||||
@ -20,6 +22,9 @@ namespace cv
|
||||
{
|
||||
namespace gapi
|
||||
{
|
||||
|
||||
namespace ocv { GAPI_EXPORTS cv::gapi::GKernelPackage kernels(); }
|
||||
|
||||
namespace wip
|
||||
{
|
||||
namespace draw
|
||||
@ -78,7 +83,38 @@ struct Line
|
||||
int thick; //!< The thickness of line
|
||||
int lt; //!< The Type of the line. See #LineTypes
|
||||
int shift; //!< The number of fractional bits in the point coordinates
|
||||
};
|
||||
|
||||
/**
|
||||
* A structure to represent parameters for drawing a mosaic
|
||||
*/
|
||||
struct Mosaic
|
||||
{
|
||||
cv::Rect mos; //!< Coordinates of the mosaic
|
||||
int cellSz; //!< Cell size (same for X, Y). Note: mos size must be multiple of cell size
|
||||
int decim; //!< Decimation (0 stands for no decimation)
|
||||
};
|
||||
|
||||
/**
|
||||
* A structure to represent parameters for drawing an image
|
||||
*/
|
||||
struct Image
|
||||
{
|
||||
cv::Point org; //!< The bottom-left corner of the image
|
||||
cv::Mat img; //!< Image to draw
|
||||
cv::Mat alpha; //!< Alpha channel for image to draw (same size and number of channels)
|
||||
};
|
||||
|
||||
/**
|
||||
* A structure to represent parameters for drawing a polygon
|
||||
*/
|
||||
struct Poly
|
||||
{
|
||||
std::vector<cv::Point> points; //!< Points to connect
|
||||
cv::Scalar color; //!< The line color
|
||||
int thick; //!< The thickness of line
|
||||
int lt; //!< The Type of the line. See #LineTypes
|
||||
int shift; //!< The number of fractional bits in the point coordinates
|
||||
};
|
||||
|
||||
using Prim = util::variant
|
||||
@ -86,27 +122,56 @@ using Prim = util::variant
|
||||
, Rect
|
||||
, Circle
|
||||
, Line
|
||||
, Mosaic
|
||||
, Image
|
||||
, Poly
|
||||
>;
|
||||
|
||||
using Prims = std::vector<Prim>;
|
||||
using GMat2 = std::tuple<cv::GMat,cv::GMat>;
|
||||
using GMatDesc2 = std::tuple<cv::GMatDesc,cv::GMatDesc>;
|
||||
|
||||
G_TYPED_KERNEL_M(GRenderNV12, <GMat2(cv::GMat,cv::GMat,cv::GArray<wip::draw::Prim>)>, "org.opencv.render.nv12")
|
||||
{
|
||||
static GMatDesc2 outMeta(GMatDesc y_plane, GMatDesc uv_plane, GArrayDesc)
|
||||
{
|
||||
return std::make_tuple(y_plane, uv_plane);
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(GRenderBGR, <cv::GMat(cv::GMat,cv::GArray<wip::draw::Prim>)>, "org.opencv.render.bgr")
|
||||
{
|
||||
static GMatDesc outMeta(GMatDesc bgr, GArrayDesc)
|
||||
{
|
||||
return bgr;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief The function renders on the input image passed drawing primitivies
|
||||
|
||||
@param bgr input image: 8-bit unsigned 3-channel image @ref CV_8UC3.
|
||||
@param prims vector of drawing primitivies
|
||||
@param pkg contains render kernel implementation
|
||||
*/
|
||||
GAPI_EXPORTS void render(cv::Mat& bgr, const Prims& prims);
|
||||
GAPI_EXPORTS void render(cv::Mat& bgr,
|
||||
const Prims& prims,
|
||||
const cv::gapi::GKernelPackage& pkg = ocv::kernels());
|
||||
|
||||
/** @brief The function renders on two NV12 planes passed drawing primitivies
|
||||
|
||||
@param y_plane input image: 8-bit unsigned 1-channel image @ref CV_8UC1.
|
||||
@param uv_plane input image: 8-bit unsigned 2-channel image @ref CV_8UC2.
|
||||
@param prims vector of drawing primitivies
|
||||
@param pkg contains render kernel implementation
|
||||
*/
|
||||
GAPI_EXPORTS void render(cv::Mat& y_plane, cv::Mat& uv_plane , const Prims& prims);
|
||||
GAPI_EXPORTS void render(cv::Mat& y_plane,
|
||||
cv::Mat& uv_plane,
|
||||
const Prims& prims,
|
||||
const cv::gapi::GKernelPackage& pkg = ocv::kernels());
|
||||
|
||||
} // namespace draw
|
||||
} // namespace wip
|
||||
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
||||
|
@ -1,91 +1,50 @@
|
||||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
#include "opencv2/gapi/render.hpp"
|
||||
#include "opencv2/gapi/own/assert.hpp"
|
||||
#include <opencv2/gapi/render.hpp>
|
||||
#include <opencv2/gapi/own/assert.hpp>
|
||||
|
||||
#include "api/render_priv.hpp"
|
||||
|
||||
using namespace cv::gapi::wip::draw;
|
||||
// FXIME util::visitor ?
|
||||
void cv::gapi::wip::draw::render(cv::Mat& bgr, const Prims& prims)
|
||||
void cv::gapi::wip::draw::render(cv::Mat &bgr,
|
||||
const cv::gapi::wip::draw::Prims &prims,
|
||||
const cv::gapi::GKernelPackage& pkg)
|
||||
{
|
||||
for (const auto& p : prims)
|
||||
{
|
||||
switch (p.index())
|
||||
{
|
||||
case Prim::index_of<Rect>():
|
||||
{
|
||||
const auto& t_p = cv::util::get<Rect>(p);
|
||||
cv::rectangle(bgr, t_p.rect, t_p.color , t_p.thick, t_p.lt, t_p.shift);
|
||||
break;
|
||||
}
|
||||
cv::GMat in;
|
||||
cv::GArray<Prim> arr;
|
||||
|
||||
case Prim::index_of<Text>():
|
||||
{
|
||||
const auto& t_p = cv::util::get<Text>(p);
|
||||
cv::putText(bgr, t_p.text, t_p.org, t_p.ff, t_p.fs,
|
||||
t_p.color, t_p.thick, t_p.lt, t_p.bottom_left_origin);
|
||||
break;
|
||||
}
|
||||
|
||||
case Prim::index_of<Circle>():
|
||||
{
|
||||
const auto& c_p = cv::util::get<Circle>(p);
|
||||
cv::circle(bgr, c_p.center, c_p.radius, c_p.color, c_p.thick, c_p.lt, c_p.shift);
|
||||
break;
|
||||
}
|
||||
|
||||
case Prim::index_of<Line>():
|
||||
{
|
||||
const auto& l_p = cv::util::get<Line>(p);
|
||||
cv::line(bgr, l_p.pt1, l_p.pt2, l_p.color, l_p.thick, l_p.lt, l_p.shift);
|
||||
break;
|
||||
}
|
||||
|
||||
default: util::throw_error(std::logic_error("Unsupported draw operation"));
|
||||
}
|
||||
}
|
||||
cv::GComputation comp(cv::GIn(in, arr),
|
||||
cv::GOut(cv::gapi::wip::draw::GRenderBGR::on(in, arr)));
|
||||
comp.apply(cv::gin(bgr, prims), cv::gout(bgr), cv::compile_args(pkg));
|
||||
}
|
||||
|
||||
void cv::gapi::wip::draw::render(cv::Mat& y_plane, cv::Mat& uv_plane , const Prims& prims)
|
||||
void cv::gapi::wip::draw::render(cv::Mat &y_plane,
|
||||
cv::Mat &uv_plane,
|
||||
const Prims &prims,
|
||||
const GKernelPackage& pkg)
|
||||
{
|
||||
cv::Mat bgr;
|
||||
cv::cvtColorTwoPlane(y_plane, uv_plane, bgr, cv::COLOR_YUV2BGR_NV12);
|
||||
render(bgr, prims);
|
||||
BGR2NV12(bgr, y_plane, uv_plane);
|
||||
cv::GMat y_in, uv_in, y_out, uv_out;
|
||||
cv::GArray<Prim> arr;
|
||||
std::tie(y_out, uv_out) = cv::gapi::wip::draw::GRenderNV12::on(y_in, uv_in, arr);
|
||||
|
||||
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
|
||||
comp.apply(cv::gin(y_plane, uv_plane, prims),
|
||||
cv::gout(y_plane, uv_plane),
|
||||
cv::compile_args(pkg));
|
||||
}
|
||||
|
||||
void cv::gapi::wip::draw::splitNV12TwoPlane(const cv::Mat& yuv, cv::Mat& y_plane, cv::Mat& uv_plane) {
|
||||
y_plane.create(yuv.size(), CV_8UC1);
|
||||
uv_plane.create(yuv.size() / 2, CV_8UC2);
|
||||
|
||||
// Fill Y plane
|
||||
for (int i = 0; i < yuv.rows; ++i)
|
||||
{
|
||||
const uchar* in = yuv.ptr<uchar>(i);
|
||||
uchar* out = y_plane.ptr<uchar>(i);
|
||||
for (int j = 0; j < yuv.cols; j++) {
|
||||
out[j] = in[3 * j];
|
||||
}
|
||||
}
|
||||
|
||||
// Fill UV plane
|
||||
for (int i = 0; i < uv_plane.rows; i++)
|
||||
{
|
||||
const uchar* in = yuv.ptr<uchar>(2 * i);
|
||||
uchar* out = uv_plane.ptr<uchar>(i);
|
||||
for (int j = 0; j < uv_plane.cols; j++) {
|
||||
out[j * 2 ] = in[6 * j + 1];
|
||||
out[j * 2 + 1] = in[6 * j + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cv::gapi::wip::draw::BGR2NV12(const cv::Mat& bgr, cv::Mat& y_plane, cv::Mat& uv_plane)
|
||||
void cv::gapi::wip::draw::BGR2NV12(const cv::Mat &bgr,
|
||||
cv::Mat &y_plane,
|
||||
cv::Mat &uv_plane)
|
||||
{
|
||||
GAPI_Assert(bgr.size().width % 2 == 0);
|
||||
GAPI_Assert(bgr.size().height % 2 == 0);
|
||||
|
||||
cvtColor(bgr, bgr, cv::COLOR_BGR2YUV);
|
||||
splitNV12TwoPlane(bgr, y_plane, uv_plane);
|
||||
cv::Mat yuv;
|
||||
cvtColor(bgr, yuv, cv::COLOR_BGR2YUV);
|
||||
|
||||
std::vector<cv::Mat> chs(3);
|
||||
cv::split(yuv, chs);
|
||||
y_plane = chs[0];
|
||||
|
||||
cv::merge(std::vector<cv::Mat>{chs[1], chs[2]}, uv_plane);
|
||||
cv::resize(uv_plane, uv_plane, uv_plane.size() / 2, cv::INTER_LINEAR);
|
||||
}
|
||||
|
226
modules/gapi/src/api/render_ocv.cpp
Normal file
226
modules/gapi/src/api/render_ocv.cpp
Normal file
@ -0,0 +1,226 @@
|
||||
#include <opencv2/gapi/cpu/gcpukernel.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/gapi/render.hpp> // Kernel API's
|
||||
|
||||
#include "api/render_ocv.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace gapi
|
||||
{
|
||||
|
||||
namespace ocv
|
||||
{
|
||||
|
||||
GAPI_OCV_KERNEL(GOCVRenderNV12, cv::gapi::wip::draw::GRenderNV12)
|
||||
{
|
||||
static void run(const cv::Mat& y, const cv::Mat& uv, const cv::gapi::wip::draw::Prims& prims,
|
||||
cv::Mat& out_y, cv::Mat& out_uv)
|
||||
{
|
||||
/* FIXME How to render correctly on NV12 format ?
|
||||
*
|
||||
* Rendering on NV12 via OpenCV looks like this:
|
||||
*
|
||||
* y --------> 1)(NV12 -> YUV) -> yuv -> 2)draw -> yuv -> 3)split -------> out_y
|
||||
* ^ |
|
||||
* | |
|
||||
* uv -------------- `----------> out_uv
|
||||
*
|
||||
*
|
||||
* 1) Collect yuv mat from two planes, uv plain in two times less than y plane
|
||||
* so, upsample uv in tow times, with bilinear interpolation
|
||||
*
|
||||
* 2) Render primitives on YUV
|
||||
*
|
||||
* 3) Convert yuv to NV12 (using bilinear interpolation)
|
||||
*
|
||||
*/
|
||||
|
||||
// NV12 -> YUV
|
||||
cv::Mat upsample_uv, yuv;
|
||||
cv::resize(uv, upsample_uv, uv.size() * 2, cv::INTER_LINEAR);
|
||||
cv::merge(std::vector<cv::Mat>{y, upsample_uv}, yuv);
|
||||
|
||||
cv::gapi::wip::draw::drawPrimitivesOCVYUV(yuv, prims);
|
||||
|
||||
// YUV -> NV12
|
||||
cv::Mat out_u, out_v, uv_plane;
|
||||
std::vector<cv::Mat> chs = {out_y, out_u, out_v};
|
||||
cv::split(yuv, chs);
|
||||
cv::merge(std::vector<cv::Mat>{chs[1], chs[2]}, uv_plane);
|
||||
cv::resize(uv_plane, out_uv, uv_plane.size() / 2, cv::INTER_LINEAR);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_OCV_KERNEL(GOCVRenderBGR, cv::gapi::wip::draw::GRenderBGR)
|
||||
{
|
||||
static void run(const cv::Mat&, const cv::gapi::wip::draw::Prims& prims, cv::Mat& out)
|
||||
{
|
||||
cv::gapi::wip::draw::drawPrimitivesOCVBGR(out, prims);
|
||||
}
|
||||
};
|
||||
|
||||
cv::gapi::GKernelPackage kernels()
|
||||
{
|
||||
static const auto pkg = cv::gapi::kernels<GOCVRenderNV12, GOCVRenderBGR>();
|
||||
return pkg;
|
||||
}
|
||||
|
||||
} // namespace ocv
|
||||
|
||||
namespace wip
|
||||
{
|
||||
namespace draw
|
||||
{
|
||||
|
||||
void mosaic(cv::Mat mat, const cv::Rect &rect, int cellSz);
|
||||
void image(cv::Mat mat, cv::Point org, cv::Mat img, cv::Mat alpha);
|
||||
void poly(cv::Mat mat, std::vector<cv::Point>, cv::Scalar color, int lt, int shift);
|
||||
|
||||
void mosaic(cv::Mat mat, const cv::Rect &rect, int cellSz)
|
||||
{
|
||||
cv::Mat msc_roi = mat(rect);
|
||||
int crop_x = msc_roi.cols - msc_roi.cols % cellSz;
|
||||
int crop_y = msc_roi.rows - msc_roi.rows % cellSz;
|
||||
|
||||
for(int i = 0; i < crop_y; i += cellSz )
|
||||
for(int j = 0; j < crop_x; j += cellSz) {
|
||||
auto cell_roi = msc_roi(cv::Rect(j, i, cellSz, cellSz));
|
||||
cell_roi = cv::mean(cell_roi);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void image(cv::Mat mat, cv::Point org, cv::Mat img, cv::Mat alpha)
|
||||
{
|
||||
auto roi = mat(cv::Rect(org.x, org.y, img.size().width, img.size().height));
|
||||
cv::Mat img32f_w;
|
||||
cv::merge(std::vector<cv::Mat>(3, alpha), img32f_w);
|
||||
|
||||
cv::Mat roi32f_w(roi.size(), CV_32FC3, cv::Scalar::all(1.0));
|
||||
roi32f_w -= img32f_w;
|
||||
|
||||
cv::Mat img32f, roi32f;
|
||||
img.convertTo(img32f, CV_32F, 1.0/255);
|
||||
roi.convertTo(roi32f, CV_32F, 1.0/255);
|
||||
|
||||
cv::multiply(img32f, img32f_w, img32f);
|
||||
cv::multiply(roi32f, roi32f_w, roi32f);
|
||||
roi32f += img32f;
|
||||
|
||||
roi32f.convertTo(roi, CV_8U, 255.0);
|
||||
};
|
||||
|
||||
void poly(cv::Mat mat, std::vector<cv::Point> points, cv::Scalar color, int lt, int shift)
|
||||
{
|
||||
std::vector<std::vector<cv::Point>> pp{points};
|
||||
cv::fillPoly(mat, pp, color, lt, shift);
|
||||
};
|
||||
|
||||
struct BGR2YUVConverter
|
||||
{
|
||||
cv::Scalar cvtColor(const cv::Scalar& bgr) const
|
||||
{
|
||||
double y = bgr[2] * 0.299000 + bgr[1] * 0.587000 + bgr[0] * 0.114000;
|
||||
double u = bgr[2] * -0.168736 + bgr[1] * -0.331264 + bgr[0] * 0.500000 + 128;
|
||||
double v = bgr[2] * 0.500000 + bgr[1] * -0.418688 + bgr[0] * -0.081312 + 128;
|
||||
|
||||
return {y, u, v};
|
||||
}
|
||||
|
||||
void cvtImg(const cv::Mat& in, cv::Mat& out) { cv::cvtColor(in, out, cv::COLOR_BGR2YUV); };
|
||||
};
|
||||
|
||||
struct EmptyConverter
|
||||
{
|
||||
cv::Scalar cvtColor(const cv::Scalar& bgr) const { return bgr; };
|
||||
void cvtImg(const cv::Mat& in, cv::Mat& out) const { out = in; };
|
||||
};
|
||||
|
||||
// FIXME util::visitor ?
|
||||
template <typename ColorConverter>
|
||||
void drawPrimitivesOCV(cv::Mat &in, const Prims &prims)
|
||||
{
|
||||
ColorConverter converter;
|
||||
for (const auto &p : prims)
|
||||
{
|
||||
switch (p.index())
|
||||
{
|
||||
case Prim::index_of<Rect>():
|
||||
{
|
||||
const auto& t_p = cv::util::get<Rect>(p);
|
||||
const auto color = converter.cvtColor(t_p.color);
|
||||
cv::rectangle(in, t_p.rect, color , t_p.thick, t_p.lt, t_p.shift);
|
||||
break;
|
||||
}
|
||||
|
||||
case Prim::index_of<Text>():
|
||||
{
|
||||
const auto& t_p = cv::util::get<Text>(p);
|
||||
const auto color = converter.cvtColor(t_p.color);
|
||||
cv::putText(in, t_p.text, t_p.org, t_p.ff, t_p.fs,
|
||||
color, t_p.thick, t_p.lt, t_p.bottom_left_origin);
|
||||
break;
|
||||
}
|
||||
|
||||
case Prim::index_of<Circle>():
|
||||
{
|
||||
const auto& c_p = cv::util::get<Circle>(p);
|
||||
const auto color = converter.cvtColor(c_p.color);
|
||||
cv::circle(in, c_p.center, c_p.radius, color, c_p.thick, c_p.lt, c_p.shift);
|
||||
break;
|
||||
}
|
||||
|
||||
case Prim::index_of<Line>():
|
||||
{
|
||||
const auto& l_p = cv::util::get<Line>(p);
|
||||
const auto color = converter.cvtColor(l_p.color);
|
||||
cv::line(in, l_p.pt1, l_p.pt2, color, l_p.thick, l_p.lt, l_p.shift);
|
||||
break;
|
||||
}
|
||||
|
||||
case Prim::index_of<Mosaic>():
|
||||
{
|
||||
const auto& l_p = cv::util::get<Mosaic>(p);
|
||||
mosaic(in, l_p.mos, l_p.cellSz);
|
||||
break;
|
||||
}
|
||||
|
||||
case Prim::index_of<Image>():
|
||||
{
|
||||
const auto& i_p = cv::util::get<Image>(p);
|
||||
|
||||
cv::Mat img;
|
||||
converter.cvtImg(i_p.img, img);
|
||||
|
||||
image(in, i_p.org, img, i_p.alpha);
|
||||
break;
|
||||
}
|
||||
|
||||
case Prim::index_of<Poly>():
|
||||
{
|
||||
const auto& p_p = cv::util::get<Poly>(p);
|
||||
const auto color = converter.cvtColor(p_p.color);
|
||||
poly(in, p_p.points, color, p_p.lt, p_p.shift);
|
||||
break;
|
||||
}
|
||||
|
||||
default: cv::util::throw_error(std::logic_error("Unsupported draw operation"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawPrimitivesOCVBGR(cv::Mat &in, const Prims &prims)
|
||||
{
|
||||
drawPrimitivesOCV<EmptyConverter>(in, prims);
|
||||
}
|
||||
|
||||
void drawPrimitivesOCVYUV(cv::Mat &in, const Prims &prims)
|
||||
{
|
||||
drawPrimitivesOCV<BGR2YUVConverter>(in, prims);
|
||||
}
|
||||
|
||||
} // namespace draw
|
||||
} // namespace wip
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
25
modules/gapi/src/api/render_ocv.hpp
Normal file
25
modules/gapi/src/api/render_ocv.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include <vector>
|
||||
#include "render_priv.hpp"
|
||||
|
||||
#ifndef OPENCV_RENDER_OCV_HPP
|
||||
#define OPENCV_RENDER_OCV_HPP
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace gapi
|
||||
{
|
||||
namespace wip
|
||||
{
|
||||
namespace draw
|
||||
{
|
||||
|
||||
// FIXME only for tests
|
||||
void GAPI_EXPORTS drawPrimitivesOCVYUV(cv::Mat &yuv, const Prims &prims);
|
||||
void GAPI_EXPORTS drawPrimitivesOCVBGR(cv::Mat &bgr, const Prims &prims);
|
||||
|
||||
} // namespace draw
|
||||
} // namespace wip
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_RENDER_OCV_HPP
|
@ -18,9 +18,9 @@ namespace wip
|
||||
{
|
||||
namespace draw
|
||||
{
|
||||
|
||||
// FIXME only for tests
|
||||
GAPI_EXPORTS void BGR2NV12(const cv::Mat& bgr, cv::Mat& y_plane, cv::Mat& uv_plane);
|
||||
void splitNV12TwoPlane(const cv::Mat& yuv, cv::Mat& y_plane, cv::Mat& uv_plane);
|
||||
|
||||
} // namespace draw
|
||||
} // namespace wip
|
||||
|
@ -10,14 +10,53 @@
|
||||
|
||||
#include "gapi_tests_common.hpp"
|
||||
#include "api/render_priv.hpp"
|
||||
#include "api/render_ocv.hpp"
|
||||
|
||||
#define rect1 Prim{cv::gapi::wip::draw::Rect{cv::Rect{101, 101, 199, 199}, cv::Scalar{153, 172, 58}, 1, LINE_8, 0}}
|
||||
#define rect2 Prim{cv::gapi::wip::draw::Rect{cv::Rect{100, 100, 199, 199}, cv::Scalar{153, 172, 58}, 1, LINE_8, 0}}
|
||||
#define rect3 Prim{cv::gapi::wip::draw::Rect{cv::Rect{0 , 0 , 199, 199}, cv::Scalar{153, 172, 58}, 1, LINE_8, 0}}
|
||||
#define rect4 Prim{cv::gapi::wip::draw::Rect{cv::Rect{100, 100, 0, 199 }, cv::Scalar{153, 172, 58}, 1, LINE_8, 0}}
|
||||
#define rect5 Prim{cv::gapi::wip::draw::Rect{cv::Rect{0 , -1 , 199, 199}, cv::Scalar{153, 172, 58}, 1, LINE_8, 0}}
|
||||
#define rect6 Prim{cv::gapi::wip::draw::Rect{cv::Rect{100, 100, 199, 199}, cv::Scalar{153, 172, 58}, 10, LINE_8, 0}}
|
||||
#define rect7 Prim{cv::gapi::wip::draw::Rect{cv::Rect{100, 100, 200, 200}, cv::Scalar{153, 172, 58}, 1, LINE_8, 0}}
|
||||
#define box1 Prim{cv::gapi::wip::draw::Rect{cv::Rect{101, 101, 200, 200}, cv::Scalar{153, 172, 58}, -1, LINE_8, 0}}
|
||||
#define box2 Prim{cv::gapi::wip::draw::Rect{cv::Rect{100, 100, 199, 199}, cv::Scalar{153, 172, 58}, -1, LINE_8, 0}}
|
||||
#define rects Prims{rect1, rect2, rect3, rect4, rect5, rect6, rect7, box1, box2}
|
||||
|
||||
#define circle1 Prim{cv::gapi::wip::draw::Circle{cv::Point{200, 200}, 100, cv::Scalar{153, 172, 58}, 1, LINE_8, 0}}
|
||||
#define circle2 Prim{cv::gapi::wip::draw::Circle{cv::Point{10, 30} , 2 , cv::Scalar{153, 172, 58}, 1, LINE_8, 0}}
|
||||
#define circle3 Prim{cv::gapi::wip::draw::Circle{cv::Point{75, 100} , 50 , cv::Scalar{153, 172, 58}, 5, LINE_8, 0}}
|
||||
#define circles Prims{circle1, circle2, circle3}
|
||||
|
||||
#define line1 Prim{cv::gapi::wip::draw::Line{cv::Point{50, 50}, cv::Point{250, 200}, cv::Scalar{153, 172, 58}, 1, LINE_8, 0}}
|
||||
#define line2 Prim{cv::gapi::wip::draw::Line{cv::Point{51, 51}, cv::Point{51, 100}, cv::Scalar{153, 172, 58}, 1, LINE_8, 0}}
|
||||
#define lines Prims{line1, line2}
|
||||
|
||||
#define mosaic1 Prim{cv::gapi::wip::draw::Mosaic{cv::Rect{100, 100, 200, 200}, 5, 0}}
|
||||
#define mosaics Prims{mosaic1}
|
||||
|
||||
#define image1 Prim{cv::gapi::wip::draw::Image{cv::Point(100, 100), cv::Mat(cv::Size(200, 200), CV_8UC3, cv::Scalar::all(255)),\
|
||||
cv::Mat(cv::Size(200, 200), CV_32FC1, cv::Scalar::all(1))}}
|
||||
|
||||
#define image2 Prim{cv::gapi::wip::draw::Image{cv::Point(100, 100), cv::Mat(cv::Size(200, 200), CV_8UC3, cv::Scalar::all(255)),\
|
||||
cv::Mat(cv::Size(200, 200), CV_32FC1, cv::Scalar::all(0.5))}}
|
||||
|
||||
#define image3 Prim{cv::gapi::wip::draw::Image{cv::Point(100, 100), cv::Mat(cv::Size(200, 200), CV_8UC3, cv::Scalar::all(255)),\
|
||||
cv::Mat(cv::Size(200, 200), CV_32FC1, cv::Scalar::all(0.0))}}
|
||||
|
||||
#define images Prims{image1, image2, image3}
|
||||
|
||||
#define polygon1 Prim{cv::gapi::wip::draw::Poly{ {cv::Point{100, 100}, cv::Point{50, 200}, cv::Point{200, 30}, cv::Point{150, 50} }, cv::Scalar{153, 172, 58}, 1, LINE_8, 0} }
|
||||
#define polygons Prims{polygon1}
|
||||
|
||||
#define text1 Prim{cv::gapi::wip::draw::Text{"TheBrownFoxJump", cv::Point{100, 100}, FONT_HERSHEY_SIMPLEX, 2, cv::Scalar{102, 178, 240}, 1, LINE_8, false} }
|
||||
#define texts Prims{text1}
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
using Points = std::vector<cv::Point>;
|
||||
using Rects = std::vector<cv::Rect>;
|
||||
using PairOfPoints = std::pair<cv::Point, cv::Point>;
|
||||
using VecOfPairOfPoints = std::vector<PairOfPoints>;
|
||||
using Prims = cv::gapi::wip::draw::Prims;
|
||||
using Prim = cv::gapi::wip::draw::Prim;
|
||||
|
||||
template<class T>
|
||||
class RenderWithParam : public TestWithParam<T>
|
||||
@ -26,47 +65,50 @@ protected:
|
||||
void Init()
|
||||
{
|
||||
MatType type = CV_8UC3;
|
||||
out_mat_ocv = cv::Mat(sz, type, cv::Scalar(255));
|
||||
out_mat_gapi = cv::Mat(sz, type, cv::Scalar(255));
|
||||
|
||||
if (isNV12Format) {
|
||||
/* NB: When converting data from BGR to NV12, data loss occurs,
|
||||
* so the reference data is subjected to the same transformation
|
||||
* for correct comparison of the test results */
|
||||
cv::gapi::wip::draw::BGR2NV12(out_mat_ocv, y, uv);
|
||||
cv::cvtColorTwoPlane(y, uv, out_mat_ocv, cv::COLOR_YUV2BGR_NV12);
|
||||
}
|
||||
}
|
||||
|
||||
void Run()
|
||||
{
|
||||
if (isNV12Format) {
|
||||
cv::gapi::wip::draw::BGR2NV12(out_mat_gapi, y, uv);
|
||||
cv::gapi::wip::draw::render(y, uv, prims);
|
||||
cv::cvtColorTwoPlane(y, uv, out_mat_gapi, cv::COLOR_YUV2BGR_NV12);
|
||||
|
||||
// NB: Also due to data loss
|
||||
cv::gapi::wip::draw::BGR2NV12(out_mat_ocv, y, uv);
|
||||
cv::cvtColorTwoPlane(y, uv, out_mat_ocv, cv::COLOR_YUV2BGR_NV12);
|
||||
} else {
|
||||
cv::gapi::wip::draw::render(out_mat_gapi, prims);
|
||||
}
|
||||
mat_ocv.create(sz, type);
|
||||
mat_gapi.create(sz, type);
|
||||
cv::randu(mat_ocv, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
mat_ocv.copyTo(mat_gapi);
|
||||
}
|
||||
|
||||
cv::Size sz;
|
||||
cv::Scalar color;
|
||||
int thick;
|
||||
int lt;
|
||||
bool isNV12Format;
|
||||
std::vector<cv::gapi::wip::draw::Prim> prims;
|
||||
cv::Mat y, uv;
|
||||
cv::Mat out_mat_ocv, out_mat_gapi;
|
||||
cv::gapi::GKernelPackage pkg;
|
||||
|
||||
cv::Mat y_mat_ocv, uv_mat_ocv, y_mat_gapi, uv_mat_gapi, mat_ocv, mat_gapi;
|
||||
};
|
||||
|
||||
struct RenderTextTest : public RenderWithParam <std::tuple<cv::Size,std::string,Points,int,double,cv::Scalar,int,int,bool,bool>> {};
|
||||
struct RenderRectTest : public RenderWithParam <std::tuple<cv::Size,Rects,cv::Scalar,int,int,int,bool>> {};
|
||||
struct RenderCircleTest : public RenderWithParam <std::tuple<cv::Size,Points,int,cv::Scalar,int,int,int,bool>> {};
|
||||
struct RenderLineTest : public RenderWithParam <std::tuple<cv::Size,VecOfPairOfPoints,cv::Scalar,int,int,int,bool>> {};
|
||||
using TestArgs = std::tuple<cv::Size,cv::gapi::wip::draw::Prims,cv::gapi::GKernelPackage>;
|
||||
|
||||
struct RenderNV12 : public RenderWithParam<TestArgs>
|
||||
{
|
||||
void ComputeRef()
|
||||
{
|
||||
cv::gapi::wip::draw::BGR2NV12(mat_ocv, y_mat_ocv, uv_mat_ocv);
|
||||
|
||||
// NV12 -> YUV
|
||||
cv::Mat upsample_uv, yuv;
|
||||
cv::resize(uv_mat_ocv, upsample_uv, uv_mat_ocv.size() * 2, cv::INTER_LINEAR);
|
||||
cv::merge(std::vector<cv::Mat>{y_mat_ocv, upsample_uv}, yuv);
|
||||
|
||||
cv::gapi::wip::draw::drawPrimitivesOCVYUV(yuv, prims);
|
||||
|
||||
// YUV -> NV12
|
||||
std::vector<cv::Mat> chs(3);
|
||||
cv::split(yuv, chs);
|
||||
cv::merge(std::vector<cv::Mat>{chs[1], chs[2]}, uv_mat_ocv);
|
||||
y_mat_ocv = chs[0];
|
||||
cv::resize(uv_mat_ocv, uv_mat_ocv, uv_mat_ocv.size() / 2, cv::INTER_LINEAR);
|
||||
}
|
||||
};
|
||||
|
||||
struct RenderBGR : public RenderWithParam<TestArgs>
|
||||
{
|
||||
void ComputeRef()
|
||||
{
|
||||
cv::gapi::wip::draw::drawPrimitivesOCVBGR(mat_ocv, prims);
|
||||
}
|
||||
};
|
||||
|
||||
} // opencv_test
|
||||
|
||||
|
@ -2,93 +2,41 @@
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2018 Intel Corporation
|
||||
// Copyright (C) 2018-2019 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_RENDER_TESTS_INL_HPP
|
||||
#define OPENCV_GAPI_RENDER_TESTS_INL_HPP
|
||||
|
||||
#include "gapi_render_tests.hpp"
|
||||
|
||||
#include <opencv2/gapi/render.hpp>
|
||||
#include "gapi_render_tests.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
TEST_P(RenderTextTest, AccuracyTest)
|
||||
TEST_P(RenderNV12, AccuracyTest)
|
||||
{
|
||||
std::vector<cv::Point> points;
|
||||
std::string text;
|
||||
int ff;
|
||||
double fs;
|
||||
bool blo;
|
||||
|
||||
std::tie(sz, text, points, ff, fs, color, thick, lt, blo, isNV12Format) = GetParam();
|
||||
std::tie(sz, prims, pkg) = GetParam();
|
||||
Init();
|
||||
|
||||
for (const auto& p : points) {
|
||||
cv::putText(out_mat_ocv, text, p, ff, fs, color, thick, lt, blo);
|
||||
prims.emplace_back(cv::gapi::wip::draw::Text{text, p, ff, fs, color, thick, lt, blo});
|
||||
}
|
||||
cv::gapi::wip::draw::BGR2NV12(mat_gapi, y_mat_gapi, uv_mat_gapi);
|
||||
cv::gapi::wip::draw::render(y_mat_gapi, uv_mat_gapi, prims, pkg);
|
||||
|
||||
Run();
|
||||
ComputeRef();
|
||||
|
||||
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
|
||||
EXPECT_EQ(0, cv::norm(y_mat_gapi, y_mat_ocv));
|
||||
EXPECT_EQ(0, cv::norm(uv_mat_gapi, uv_mat_ocv));
|
||||
}
|
||||
|
||||
TEST_P(RenderRectTest, AccuracyTest)
|
||||
TEST_P(RenderBGR, AccuracyTest)
|
||||
{
|
||||
std::vector<cv::Rect> rects;
|
||||
int shift;
|
||||
|
||||
std::tie(sz, rects, color, thick, lt, shift, isNV12Format) = GetParam();
|
||||
std::tie(sz, prims, pkg) = GetParam();
|
||||
Init();
|
||||
|
||||
for (const auto& r : rects) {
|
||||
cv::rectangle(out_mat_ocv, r, color, thick, lt, shift);
|
||||
prims.emplace_back(cv::gapi::wip::draw::Rect{r, color, thick, lt, shift});
|
||||
}
|
||||
cv::gapi::wip::draw::render(mat_gapi, prims, pkg);
|
||||
ComputeRef();
|
||||
|
||||
Run();
|
||||
|
||||
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
|
||||
}
|
||||
|
||||
TEST_P(RenderCircleTest, AccuracyTest)
|
||||
{
|
||||
std::vector<cv::Point> points;
|
||||
int radius;
|
||||
int shift;
|
||||
|
||||
std::tie(sz, points, radius, color, thick, lt, shift, isNV12Format) = GetParam();
|
||||
Init();
|
||||
|
||||
for (const auto& p : points) {
|
||||
cv::circle(out_mat_ocv, p, radius, color, thick, lt, shift);
|
||||
prims.emplace_back(cv::gapi::wip::draw::Circle{p, radius, color, thick, lt, shift});
|
||||
}
|
||||
|
||||
Run();
|
||||
|
||||
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
|
||||
}
|
||||
|
||||
TEST_P(RenderLineTest, AccuracyTest)
|
||||
{
|
||||
std::vector<std::pair<cv::Point, cv::Point>> points;
|
||||
int shift;
|
||||
|
||||
std::tie(sz, points, color, thick, lt, shift, isNV12Format) = GetParam();
|
||||
Init();
|
||||
|
||||
for (const auto& p : points) {
|
||||
cv::line(out_mat_ocv, p.first, p.second, color, thick, lt, shift);
|
||||
prims.emplace_back(cv::gapi::wip::draw::Line{p.first, p.second, color, thick, lt, shift});
|
||||
}
|
||||
|
||||
Run();
|
||||
|
||||
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
|
||||
EXPECT_EQ(0, cv::norm(mat_gapi, mat_ocv));
|
||||
}
|
||||
|
||||
} // opencv_test
|
||||
|
@ -11,56 +11,92 @@
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderTextTestCPU, RenderTextTest,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480),
|
||||
cv::Size(128, 128)),
|
||||
Values("text"),
|
||||
Values(Points{Point(5, 30), Point(40, 70), Point(-1, -1)}),
|
||||
/* Font face */ Values(FONT_HERSHEY_SIMPLEX),
|
||||
/* Font scale */ Values(2),
|
||||
/* Color */ Values(cv::Scalar(255, 0, 0)),
|
||||
/* Thickness */ Values(1),
|
||||
/* Line type */ Values(LINE_8),
|
||||
/* Bottom left origin */ testing::Bool(),
|
||||
/* NV12 format or not */ testing::Bool()));
|
||||
#define OCV cv::gapi::ocv::kernels()
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderRectTestCPU, RenderRectTest,
|
||||
/* NV12 test cases */
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVRects, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480),
|
||||
cv::Size(128, 128)),
|
||||
Values(Rects{Rect(5, 30, 40, 50),
|
||||
Rect(40, 70, 40, 50),
|
||||
/* Edge case, rectangle will not be drawn */ Rect(75, 110, -40, 50),
|
||||
/* Edge case, rectangle will not be drawn */ Rect(70, 100, 0, 50)}),
|
||||
/* Color */ Values(cv::Scalar(255, 0, 0)),
|
||||
/* Thickness */ Values(1),
|
||||
/* Line type */ Values(LINE_8),
|
||||
/* Shift */ Values(0),
|
||||
/* NV12 format or not */ testing::Bool()));
|
||||
cv::Size(640, 480)),
|
||||
Values(rects),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderCircleTestCPU, RenderCircleTest,
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVCircles, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480),
|
||||
cv::Size(128, 128)),
|
||||
Values(Points{Point(5, 30), Point(40, 70), Point(75, 110)}),
|
||||
/* Radius */ Values(5),
|
||||
/* Color */ Values(cv::Scalar(255, 0, 0)),
|
||||
/* Thickness */ Values(1),
|
||||
/* Line type */ Values(LINE_8),
|
||||
/* Shift */ Values(0),
|
||||
/* NV12 format or not */ testing::Bool()));
|
||||
cv::Size(640, 480)),
|
||||
Values(circles),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderLineTestCPU, RenderLineTest,
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVLines, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480),
|
||||
cv::Size(128, 128)),
|
||||
Values(VecOfPairOfPoints{ {Point(5, 30) , Point(5, 40) },
|
||||
{Point(40, 70) , Point(50, 70) },
|
||||
{Point(75, 110), Point(100, 115)} }),
|
||||
/* Color */ Values(cv::Scalar(255, 0, 0)),
|
||||
/* Thickness */ Values(1),
|
||||
/* Line type */ Values(LINE_8),
|
||||
/* Shift */ Values(0),
|
||||
/* NV12 format or not */ testing::Bool()));
|
||||
cv::Size(640, 480)),
|
||||
Values(lines),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVMosaics, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(mosaics),
|
||||
Values(OCV)));
|
||||
|
||||
// FIXME difference in color
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVImages, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(images),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVPolygons, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(polygons),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVTexts, RenderNV12,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(texts),
|
||||
Values(OCV)));
|
||||
|
||||
/* BGR test cases */
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVRects, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(rects),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVCircles, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(circles),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVLines, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(lines),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVMosaics, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(mosaics),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVImages, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(images),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVPolygons, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(polygons),
|
||||
Values(OCV)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderBGROCVTexts, RenderBGR,
|
||||
Combine(Values(cv::Size(1280, 720),
|
||||
cv::Size(640, 480)),
|
||||
Values(texts),
|
||||
Values(OCV)));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user