This is free SDK for MSU VQMT. Using this toolset you can create own plugin that
- can have 1 or 2 input videos (RGB or YUV float planes)
- produce arbitrary number of outputs (float number for each frame of input video(s))
- produce visualization (image for every frame)
- can be configurable
Each plugin creates own metric, that can be used in VQMT.
SDK can be used with FREE as well as in PRO VQMT edition.
You can build Sample Plugin with CMake utility.
- Download & install CMake.
- Open CMake GUI tool
- Select
<VQMT SDK install path>/sample_plugin/build
as Source code directory, fill directory for the binaries - Press "Configure" and select Visual Studio with x64 platform
- Press "Generate" and "Open Project"
- Build generated solution
- Install CMake
- Goto folder, where you want to place binaries and type cmake /sample_plugin/build make
Goto VQMT installation and place output .vmp
file into folder plugins
Place output .vmp
file into folder ~/.msu_vqmt/plugins
Create CMake project using Sample Plugin cmake as a template. If you don't want to use CMake, you should create static library with exports, described in section Understanging SDK structure and exports. That library should be saved with .vmp
extension.
As soon project is created, you should create a class for your plugin that inherits ICustomPlugin
from ICustomPlugin.h
.
This class must implement the following member-functions:
void Init(IMetricImage::ColorComponent cc, int width, int height, IMetricPlugin::ID start_id, IMetricValueSink* valueSink);
std::vector<std::pair<IMetricPlugin::ID, float>> Measure(std::vector<IMetricImage*> &images);
std::vector<std::pair<IMetricPlugin::ID, float>> MeasureAndVisualize(std::vector<IMetricImage*>&images, unsigned char *vis, int vis_pitch);
std::vector<IDinfo> MapIDToFrame(bool visualize);
std::vector<std::pair<IMetricPlugin::ID, float>> CalculateAverage(bool visualize);
int GetVideoNum(bool visualize);
std::vector <IMetricImage::ColorComponent> GetSupportedColorcomponents();
std::wstring GetName();
std::wstring GetInterfaceName();
std::wstring GetLongName();
std::wstring GetUnit();
std::wstring GetMetrInfoURL();
bool GetMetrIncline();
And can implement the following functions:
void Stop();
const std::wstring& GetConfigJSON();
bool SetConfigParams(const std::wstring& json);
std::wstring GetConfigSummary();
The mean of each overriten member described in the following sections.
void Init(IMetricImage::ColorComponent cc, int width, int height, IMetricPlugin::ID start_id, IMetricValueSink* valueSink);
Color component, that is written to cc
is one of values returned by prior GetSupportedColorcomponents()
call.
This function will be called before measurement started. width
and height
are constant during all measurement.
Param start_id
is using to index output values of plugin. If plugin should provide N float results for each frame, they should have following ids:
start_id
, start_id
+1, ..., start_id
+N-1.
You can save valueSink
if you need to provide results at any time. Not all plugins should use valueSink
.
std::vector<IDinfo> MapIDToFrame(bool visualize);
This function can give a name each result type. If you plugin provides N float results for each frame, the output should be an std::vector of N elements. You can distinguish the case of saving visualization and working without visualization save by visualize
param.
int GetVideoNum(bool visualize);
This function should return value 2 for reference metric and 1 for non-reference. Other values are not supported. You can distinguish the case of saving visualization and working without visualization save by visualize
param.
std::vector <IMetricImage::ColorComponent> GetSupportedColorcomponents();
You can allow user to run metric with only specified color components. Color components supported at this moment are: Y, U, V, R, G, B, L (for LUV). The exact color component from returned vector will be provided to plugin during initialization in Init
function.
std::wstring GetName();
This function should return name that will be used in command line to select metric. It shouldn't start with -
, shouldn't match VQMT commandline keywords, also we recommend to make it whitespace-free and start from lowercase letter.
std::wstring GetInterfaceName();
This function should return name that will be used in VQMT GUI. It can contain spaces and we recommend to start with uppercase letter.
std::wstring GetLongName();
This value will be used in the description of metric. Provide full expanded name of the metric.
std::wstring GetUnit();
This function should return short name of units for result floats. Unit name will be used in plot of metric values and in VQMT output files.
std::wstring GetMetrInfoURL();
This function should return URL of page with description of metric. It will be displayed in GUI after selecting metric and in commandline after getting metric list.
bool GetMetrIncline();
Should return true if "bigger means better" for this metric.
std::vector<std::pair<IMetricPlugin::ID, float>> Measure(std::vector<IMetricImage*> &images);
You should implement this function that will be called for each frame of VQMT input consequently in case of no visualization needed. Param images
will contain same number of images as value, returned by GetVideoNum
. Read more about input images in section Imput image format.
You should choose: to provide values by return values of this function or by using IMetricValueSink* valueSink
transmited to Init
function. Choose second way, if you want don't know metric value for frame N after processing frame N and preceeding frames. Using valueSink
you can provide value for a frame after processing any amount of subsequent frames. In that case, Measure
should return empty vector.
If you choose to tell results value by return value of Measure
, it should return same number of values as in MapIDToFrame
return value.
IMetricPlugin::ID
should be consequent, the first one should be start_id
that transmited to Init
function.
void Stop();
If you are using valueSink
, this is the last chance to use it for providing values.
Measure
should not be called after stop, also, you shouldn't use valueSink
.
std::vector<std::pair<IMetricPlugin::ID, float>> CalculateAverage(bool visualize);
Return average results in the same way as in Measure
return value. You can't use valueSink
for this task.
std::vector<std::pair<IMetricPlugin::ID, float>> MeasureAndVisualize(std::vector<IMetricImage*>&images, unsigned char *vis, int vis_pitch);
This function should do same things as Measure
. Additionally, it should save visualization into vis
argument.
vis
param points to memory that contains RGB24 image of width and height provided to Init
. Use vis_pitch
while filling this image.
const std::wstring& GetConfigJSON();
Metric can be configured. The configuration described by return value of this function. It should be JSON object, that contains paires of type "param-key": <param-description>
. The <param-description>
is object with following fields:
description
help
default_value
- this value will determine param type. It can be integer, string of floating point.possible_values
(optional) - this value should be an array. Ifdefault_value
is string, you can create enum param specifying this value.
If default_value
is numeric, you can provide 2-element array as first argument, specifying possible value range.
bool SetConfigParams(const std::wstring& json);
VQMT will send configuration provided by user via this call. It will contain JSON object with values of all parameters. You can parse JSON using library json.h
by YUVsoft included in SDK-pack.
std::wstring GetConfigSummary();
This function, called after SetConfigParams
can return short description of applied configuration.
IMetricImage
declared in IMetricImage.h
is interface that describes an image transmited to Measure
and MeasureAndVisualize
functions. It provides several image planes, only component specified in cc
param of Init
is guaranteed to be filled.
You can get width and height by calling int GetWidth() const
and int GetHeight() const
. Note, image in IMetricImage
can have width and height greater than values, provided to Init
call. You should be guided by Init
values and discard parts of the image that go beyond these boundaries.
You can get plane of image calling const float* GetX() const
where X
is one of R
, G
, B
, Y
, U
, V
, L
. This call can return nullptr
if plane is not present in image. Each row of plane consists of GetWidth()
floats, rows are not aligned are located one after another.
const RangeSpecification* GetRanges() const
This function will return array of ranges for each component in order as in IMetricImage::ColorComponent enum.
See vqmt_sample_plugin.cpp
to know, what functions you should export. You can use this file unchanged, only replaced VQMTsamplePlugin
with name of your own ICustomPlugin
implementation.
Each plugin is shared library that should export following functions:
void CreateMetric(IMetricPlugin** metric);
void ReleaseMetric(IMetricPlugin* metric);
int GetVQMTVersion();
int CompatibleWithVQMT(int vqmtVer);
CreateMetric
should create new instance of abstract class IMetricPlugin. IMetricPlugin has implementation-independent methods that are inconvenient to use, so we recommend to use ICustomPlugin
, that implements exactly the same functions as CreateMetric
but in more usable way. SDK implements wrapper CPluginAdapter
that can convert ICustomPlugin
to IMetricPlugin
.
Release metric
destroys created instance.
GetVQMTVersion
and CompatibleWithVQMT
can be used to determine whether a particular version of VQMT is compatible with the plugin. The general rule is: VQMT should know plugin SDK, i. e. newer VQMT can use older plugin, but not vice versa.