mirror of
https://github.com/opencv/opencv.git
synced 2024-12-11 14:39:11 +08:00
16b9514543
`PyObject*` to `std::vector<T>` conversion logic: - If user passed Numpy Array - If array is planar and T is a primitive type (doesn't require constructor call) that matches with the element type of array, then copy element one by one with the respect of the step between array elements. If compiler is lucky (or brave enough) copy loop can be vectorized. For classes that require constructor calls this path is not possible, because we can't begin an object lifetime without hacks. - Otherwise fall-back to general case - Otherwise - execute the general case: If PyObject* corresponds to Sequence protocol - iterate over the sequence elements and invoke the appropriate `pyopencv_to` function. `std::vector<T>` to `PyObject*` conversion logic: - If `std::vector<T>` is empty - return empty tuple. - If `T` has a corresponding `Mat` `DataType` than return Numpy array instance of the matching `dtype` e.g. `std::vector<cv::Rect>` is returned as `np.ndarray` of shape `Nx4` and `dtype=int`. This branch helps to optimize further evaluations in user code. - Otherwise - execute the general case: Construct a tuple of length N = `std::vector::size` and insert elements one by one. Unnecessary functions were removed and code was rearranged to allow compiler select the appropriate conversion function specialization.
259 lines
8.3 KiB
C++
259 lines
8.3 KiB
C++
// This file is part of OpenCV project.
|
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
|
// of this distribution and at http://opencv.org/license.html.
|
|
|
|
#include "precomp.hpp"
|
|
#include "opencv2/core/bindings_utils.hpp"
|
|
#include <sstream>
|
|
#include <iomanip>
|
|
|
|
namespace cv { namespace utils {
|
|
|
|
String dumpInputArray(InputArray argument)
|
|
{
|
|
if (&argument == &noArray())
|
|
return "InputArray: noArray()";
|
|
std::ostringstream ss;
|
|
ss << "InputArray:";
|
|
try {
|
|
do {
|
|
ss << (argument.empty() ? " empty()=true" : " empty()=false");
|
|
ss << cv::format(" kind=0x%08llx", (long long int)argument.kind());
|
|
ss << cv::format(" flags=0x%08llx", (long long int)argument.getFlags());
|
|
if (argument.getObj() == NULL)
|
|
{
|
|
ss << " obj=NULL";
|
|
break; // done
|
|
}
|
|
ss << cv::format(" total(-1)=%lld", (long long int)argument.total(-1));
|
|
int dims = argument.dims(-1);
|
|
ss << cv::format(" dims(-1)=%d", dims);
|
|
if (dims <= 2)
|
|
{
|
|
Size size = argument.size(-1);
|
|
ss << cv::format(" size(-1)=%dx%d", size.width, size.height);
|
|
}
|
|
else
|
|
{
|
|
int sz[CV_MAX_DIM] = {0};
|
|
argument.sizend(sz, -1);
|
|
ss << " size(-1)=[";
|
|
for (int i = 0; i < dims; i++)
|
|
{
|
|
if (i > 0)
|
|
ss << ' ';
|
|
ss << sz[i];
|
|
}
|
|
ss << "]";
|
|
}
|
|
ss << " type(-1)=" << cv::typeToString(argument.type(-1));
|
|
} while (0);
|
|
}
|
|
catch (...)
|
|
{
|
|
ss << " ERROR: exception occurred, dump is non-complete"; // need to properly support different kinds
|
|
}
|
|
return ss.str();
|
|
}
|
|
|
|
CV_EXPORTS_W String dumpInputArrayOfArrays(InputArrayOfArrays argument)
|
|
{
|
|
if (&argument == &noArray())
|
|
return "InputArrayOfArrays: noArray()";
|
|
std::ostringstream ss;
|
|
ss << "InputArrayOfArrays:";
|
|
try {
|
|
do {
|
|
ss << (argument.empty() ? " empty()=true" : " empty()=false");
|
|
ss << cv::format(" kind=0x%08llx", (long long int)argument.kind());
|
|
ss << cv::format(" flags=0x%08llx", (long long int)argument.getFlags());
|
|
if (argument.getObj() == NULL)
|
|
{
|
|
ss << " obj=NULL";
|
|
break; // done
|
|
}
|
|
ss << cv::format(" total(-1)=%lld", (long long int)argument.total(-1));
|
|
ss << cv::format(" dims(-1)=%d", argument.dims(-1));
|
|
Size size = argument.size(-1);
|
|
ss << cv::format(" size(-1)=%dx%d", size.width, size.height);
|
|
if (argument.total(-1) > 0)
|
|
{
|
|
ss << " type(0)=" << cv::typeToString(argument.type(0));
|
|
int dims = argument.dims(0);
|
|
ss << cv::format(" dims(0)=%d", dims);
|
|
if (dims <= 2)
|
|
{
|
|
Size size0 = argument.size(0);
|
|
ss << cv::format(" size(0)=%dx%d", size0.width, size0.height);
|
|
}
|
|
else
|
|
{
|
|
int sz[CV_MAX_DIM] = {0};
|
|
argument.sizend(sz, 0);
|
|
ss << " size(0)=[";
|
|
for (int i = 0; i < dims; i++)
|
|
{
|
|
if (i > 0)
|
|
ss << ' ';
|
|
ss << sz[i];
|
|
}
|
|
ss << "]";
|
|
}
|
|
}
|
|
} while (0);
|
|
}
|
|
catch (...)
|
|
{
|
|
ss << " ERROR: exception occurred, dump is non-complete"; // need to properly support different kinds
|
|
}
|
|
return ss.str();
|
|
}
|
|
|
|
CV_EXPORTS_W String dumpInputOutputArray(InputOutputArray argument)
|
|
{
|
|
if (&argument == &noArray())
|
|
return "InputOutputArray: noArray()";
|
|
std::ostringstream ss;
|
|
ss << "InputOutputArray:";
|
|
try {
|
|
do {
|
|
ss << (argument.empty() ? " empty()=true" : " empty()=false");
|
|
ss << cv::format(" kind=0x%08llx", (long long int)argument.kind());
|
|
ss << cv::format(" flags=0x%08llx", (long long int)argument.getFlags());
|
|
if (argument.getObj() == NULL)
|
|
{
|
|
ss << " obj=NULL";
|
|
break; // done
|
|
}
|
|
ss << cv::format(" total(-1)=%lld", (long long int)argument.total(-1));
|
|
int dims = argument.dims(-1);
|
|
ss << cv::format(" dims(-1)=%d", dims);
|
|
if (dims <= 2)
|
|
{
|
|
Size size = argument.size(-1);
|
|
ss << cv::format(" size(-1)=%dx%d", size.width, size.height);
|
|
}
|
|
else
|
|
{
|
|
int sz[CV_MAX_DIM] = {0};
|
|
argument.sizend(sz, -1);
|
|
ss << " size(-1)=[";
|
|
for (int i = 0; i < dims; i++)
|
|
{
|
|
if (i > 0)
|
|
ss << ' ';
|
|
ss << sz[i];
|
|
}
|
|
ss << "]";
|
|
}
|
|
ss << " type(-1)=" << cv::typeToString(argument.type(-1));
|
|
} while (0);
|
|
}
|
|
catch (...)
|
|
{
|
|
ss << " ERROR: exception occurred, dump is non-complete"; // need to properly support different kinds
|
|
}
|
|
return ss.str();
|
|
}
|
|
|
|
CV_EXPORTS_W String dumpInputOutputArrayOfArrays(InputOutputArrayOfArrays argument)
|
|
{
|
|
if (&argument == &noArray())
|
|
return "InputOutputArrayOfArrays: noArray()";
|
|
std::ostringstream ss;
|
|
ss << "InputOutputArrayOfArrays:";
|
|
try {
|
|
do {
|
|
ss << (argument.empty() ? " empty()=true" : " empty()=false");
|
|
ss << cv::format(" kind=0x%08llx", (long long int)argument.kind());
|
|
ss << cv::format(" flags=0x%08llx", (long long int)argument.getFlags());
|
|
if (argument.getObj() == NULL)
|
|
{
|
|
ss << " obj=NULL";
|
|
break; // done
|
|
}
|
|
ss << cv::format(" total(-1)=%lld", (long long int)argument.total(-1));
|
|
ss << cv::format(" dims(-1)=%d", argument.dims(-1));
|
|
Size size = argument.size(-1);
|
|
ss << cv::format(" size(-1)=%dx%d", size.width, size.height);
|
|
if (argument.total(-1) > 0)
|
|
{
|
|
ss << " type(0)=" << cv::typeToString(argument.type(0));
|
|
int dims = argument.dims(0);
|
|
ss << cv::format(" dims(0)=%d", dims);
|
|
if (dims <= 2)
|
|
{
|
|
Size size0 = argument.size(0);
|
|
ss << cv::format(" size(0)=%dx%d", size0.width, size0.height);
|
|
}
|
|
else
|
|
{
|
|
int sz[CV_MAX_DIM] = {0};
|
|
argument.sizend(sz, 0);
|
|
ss << " size(0)=[";
|
|
for (int i = 0; i < dims; i++)
|
|
{
|
|
if (i > 0)
|
|
ss << ' ';
|
|
ss << sz[i];
|
|
}
|
|
ss << "]";
|
|
}
|
|
}
|
|
} while (0);
|
|
}
|
|
catch (...)
|
|
{
|
|
ss << " ERROR: exception occurred, dump is non-complete"; // need to properly support different kinds
|
|
}
|
|
return ss.str();
|
|
}
|
|
|
|
static inline std::ostream& operator<<(std::ostream& os, const cv::Rect& rect)
|
|
{
|
|
return os << "[x=" << rect.x << ", y=" << rect.y << ", w=" << rect.width << ", h=" << rect.height << ']';
|
|
}
|
|
|
|
template <class T, class Formatter>
|
|
static inline String dumpVector(const std::vector<T>& vec, Formatter format)
|
|
{
|
|
std::ostringstream oss("[", std::ios::ate);
|
|
if (!vec.empty())
|
|
{
|
|
oss << format << vec[0];
|
|
for (std::size_t i = 1; i < vec.size(); ++i)
|
|
{
|
|
oss << ", " << format << vec[i];
|
|
}
|
|
}
|
|
oss << "]";
|
|
return oss.str();
|
|
}
|
|
|
|
static inline std::ostream& noFormat(std::ostream& os)
|
|
{
|
|
return os;
|
|
}
|
|
|
|
static inline std::ostream& floatFormat(std::ostream& os)
|
|
{
|
|
return os << std::fixed << std::setprecision(2);
|
|
}
|
|
|
|
String dumpVectorOfInt(const std::vector<int>& vec)
|
|
{
|
|
return dumpVector(vec, &noFormat);
|
|
}
|
|
|
|
String dumpVectorOfDouble(const std::vector<double>& vec)
|
|
{
|
|
return dumpVector(vec, &floatFormat);
|
|
}
|
|
|
|
String dumpVectorOfRect(const std::vector<Rect>& vec)
|
|
{
|
|
return dumpVector(vec, &noFormat);
|
|
}
|
|
|
|
}} // namespace
|