mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge branch 4.x
This commit is contained in:
Vendored
+1
-1
@@ -21,7 +21,7 @@ if(ANDROID AND ARMEABI_V7A AND NOT NEON)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(WIN32 AND (X86_64 OR X86))
|
||||
foreach(file ${lib_srcs})
|
||||
if("${file}" MATCHES "_avx2.c")
|
||||
if(MSVC)
|
||||
|
||||
@@ -282,11 +282,17 @@ ${OPENCV_DOWNLOAD_LOG}
|
||||
ocv_download_log("#mkdir \"${DL_DESTINATION_DIR}\"")
|
||||
file(MAKE_DIRECTORY "${DL_DESTINATION_DIR}")
|
||||
ocv_download_log("#unpack \"${DL_DESTINATION_DIR}\" \"${CACHE_CANDIDATE}\"")
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E tar xzf "${CACHE_CANDIDATE}"
|
||||
WORKING_DIRECTORY "${DL_DESTINATION_DIR}"
|
||||
RESULT_VARIABLE res)
|
||||
if(NOT res EQUAL 0)
|
||||
message(FATAL_ERROR "${__msg_prefix}Unpack failed: ${res}")
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
|
||||
file(ARCHIVE_EXTRACT
|
||||
INPUT "${CACHE_CANDIDATE}"
|
||||
DESTINATION "${DL_DESTINATION_DIR}")
|
||||
else()
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E tar xzf "${CACHE_CANDIDATE}"
|
||||
WORKING_DIRECTORY "${DL_DESTINATION_DIR}"
|
||||
RESULT_VARIABLE res)
|
||||
if(NOT res EQUAL 0)
|
||||
message(FATAL_ERROR "${__msg_prefix}Unpack failed: ${res}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
ocv_download_log("#copy \"${COPY_DESTINATION}\" \"${CACHE_CANDIDATE}\"")
|
||||
|
||||
@@ -43,7 +43,12 @@ file(TO_CMAKE_PATH "${IPPROOT}" IPPROOT)
|
||||
|
||||
# This function detects Intel IPP Integration Wrappers version by analyzing .h file
|
||||
macro(ippiw_setup PATH BUILD)
|
||||
set(IPP_NEW_LAYOUT 0)
|
||||
set(FILE "${PATH}/include/iw/iw_version.h")
|
||||
if(NOT EXISTS "${FILE}")
|
||||
set(IPP_NEW_LAYOUT 1)
|
||||
set(FILE "${PATH}/include/ipp/iw/iw_version.h")
|
||||
endif()
|
||||
if(${BUILD})
|
||||
ippiw_debugmsg("Checking sources: ${PATH}")
|
||||
else()
|
||||
@@ -83,7 +88,9 @@ macro(ippiw_setup PATH BUILD)
|
||||
set(IPP_IW_LIBRARY ippiw)
|
||||
set(IPP_IW_INCLUDES "${IPP_IW_PATH}/include")
|
||||
set(IPP_IW_LIBRARIES ${IPP_IW_LIBRARY})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OpenCV_SOURCE_DIR}/3rdparty/ippicv/CMakeLists.txt" "${IPP_IW_PATH}/")
|
||||
if(NOT EXISTS "${IPP_IW_PATH}/CMakeLists.txt")
|
||||
file(COPY "${OpenCV_SOURCE_DIR}/3rdparty/ippicv/CMakeLists.txt" DESTINATION "${IPP_IW_PATH}")
|
||||
endif()
|
||||
add_subdirectory("${IPP_IW_PATH}/" ${OpenCV_BINARY_DIR}/3rdparty/ippiw)
|
||||
|
||||
set(HAVE_IPP_IW 1)
|
||||
@@ -97,11 +104,20 @@ macro(ippiw_setup PATH BUILD)
|
||||
endif()
|
||||
else()
|
||||
# check binaries
|
||||
if(IPP_X64)
|
||||
set(FILE "${PATH}/lib/intel64/${CMAKE_STATIC_LIBRARY_PREFIX}ipp_iw${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
if (IPP_NEW_LAYOUT)
|
||||
if(IPP_X64)
|
||||
set(IW_LIB_DIR "${PATH}/lib")
|
||||
else()
|
||||
set(IW_LIB_DIR "${PATH}/lib32")
|
||||
endif()
|
||||
else()
|
||||
set(FILE "${PATH}/lib/ia32/${CMAKE_STATIC_LIBRARY_PREFIX}ipp_iw${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
if(IPP_X64)
|
||||
set(IW_LIB_DIR "${PATH}/lib/intel64")
|
||||
else()
|
||||
set(IW_LIB_DIR "${PATH}/lib/ia32")
|
||||
endif()
|
||||
endif()
|
||||
set(FILE "${IW_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}ipp_iw${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
if(EXISTS ${FILE})
|
||||
ippiw_debugmsg("binaries\tyes (64=${IPP_X64})")
|
||||
set(IPP_IW_PATH "${PATH}")
|
||||
|
||||
@@ -991,7 +991,7 @@ macro(_ocv_create_module)
|
||||
ocv_target_link_libraries(${the_module} PUBLIC ${OPENCV_MODULE_${the_module}_DEPS_EXT}
|
||||
INTERFACE ${OPENCV_MODULE_${the_module}_DEPS_EXT}
|
||||
)
|
||||
ocv_target_link_libraries(${the_module} PRIVATE ${OPENCV_LINKER_LIBS} ${OPENCV_HAL_LINKER_LIBS} ${IPP_LIBS} ${ARGN})
|
||||
ocv_target_link_libraries(${the_module} PRIVATE ${OPENCV_LINKER_LIBS} ${OPENCV_HAL_LINKER_LIBS} ${ARGN})
|
||||
if (NOT ENABLE_CUDA_FIRST_CLASS_LANGUAGE AND HAVE_CUDA)
|
||||
ocv_target_link_libraries(${the_module} PRIVATE ${CUDA_LIBRARIES} ${CUDA_npp_LIBRARY})
|
||||
endif()
|
||||
|
||||
@@ -769,6 +769,22 @@
|
||||
number = {8},
|
||||
publisher = {IOP Publishing Ltd}
|
||||
}
|
||||
@article{Lourakis2009_sba,
|
||||
author = {Lourakis, Manolis I. A. and Argyros, Antonis A.},
|
||||
title = {SBA: A Software Package for Generic Sparse Bundle Adjustment},
|
||||
year = {2009},
|
||||
month = mar,
|
||||
journal = {ACM Transactions on Mathematical Software},
|
||||
volume = {36},
|
||||
number = {1},
|
||||
articleno = {2},
|
||||
pages = {2:1--2:30},
|
||||
numpages = {30},
|
||||
publisher = {Association for Computing Machinery},
|
||||
doi = {10.1145/1486525.1486527},
|
||||
url = {https://scispace.com/pdf/sba-a-software-package-for-generic-sparse-bundle-adjustment-1d4hp0z31z.pdf},
|
||||
month_numeric = {3}
|
||||
}
|
||||
@article{LowIlie2003,
|
||||
author = {Kok-Lim Low, Adrian Ilie},
|
||||
year = {2003},
|
||||
@@ -1253,6 +1269,20 @@
|
||||
publisher = {Taylor \& Francis},
|
||||
url = {https://www.olivier-augereau.com/docs/2004JGraphToolsTelea.pdf}
|
||||
}
|
||||
@incollection{Triggs2000_bundle_adjustment,
|
||||
author = {Triggs, Bill and McLauchlan, Philip F. and Hartley, Richard I. and Fitzgibbon, Andrew W.},
|
||||
title = {Bundle Adjustment---A Modern Synthesis},
|
||||
booktitle = {Vision Algorithms: Theory and Practice},
|
||||
year = {2000},
|
||||
pages = {298--372},
|
||||
publisher = {Springer},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
volume = {1883},
|
||||
editor = {Triggs, Bill and Zisserman, Andrew and Szeliski, Richard},
|
||||
doi = {10.1007/3-540-44480-7_21},
|
||||
isbn = {978-3-540-67973-8},
|
||||
url = {https://www.cs.jhu.edu/~misha/ReadingSeminar/Papers/Triggs00.pdf}
|
||||
}
|
||||
@article{Tsai89,
|
||||
author = {R. Y. Tsai and R. K. Lenz},
|
||||
journal = {IEEE Transactions on Robotics and Automation},
|
||||
|
||||
@@ -206,17 +206,17 @@ Re-projection Error
|
||||
|
||||
Re-projection error gives a good estimation of just how exact the found parameters are. The closer the re-projection error is to zero, the more accurate the parameters we found are. Given the intrinsic, distortion, rotation and translation matrices,
|
||||
we must first transform the object point to image point using **cv.projectPoints()**. Then, we can calculate
|
||||
the absolute norm between what we got with our transformation and the corner finding algorithm. To
|
||||
find the average error, we calculate the arithmetical mean of the errors calculated for all the
|
||||
calibration images.
|
||||
the norm between what we got with our transformation and the corner finding algorithm. To find the
|
||||
RMSE (root mean squared error), we average the squared errors over all points and images, then take
|
||||
the square root.
|
||||
@code{.py}
|
||||
mean_error = 0
|
||||
for i in range(len(objpoints)):
|
||||
imgpoints2, _ = cv.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
|
||||
error = cv.norm(imgpoints[i], imgpoints2, cv.NORM_L2)/len(imgpoints2)
|
||||
error = cv.norm(imgpoints[i], imgpoints2, cv.NORM_L2SQR) / len(imgpoints2)
|
||||
mean_error += error
|
||||
|
||||
print( "total error: {}".format(mean_error/len(objpoints)) )
|
||||
print( "total error: {}".format(np.sqrt(mean_error/len(objpoints))) )
|
||||
@endcode
|
||||
|
||||
Exercises
|
||||
|
||||
@@ -45,7 +45,7 @@ target_include_directories(ipphal PRIVATE
|
||||
${IPP_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(ipphal PUBLIC ${IPP_IW_LIBRARY} ${IPP_LIBRARIES})
|
||||
target_link_libraries(ipphal PUBLIC ${IPP_IW_LIBRARIES} ${IPP_LIBRARIES})
|
||||
|
||||
set_target_properties(ipphal PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH} DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}")
|
||||
|
||||
|
||||
@@ -534,6 +534,7 @@ enum { CALIB_USE_INTRINSIC_GUESS = 0x00001, //!< Use user provided intrinsics as
|
||||
// for stereo rectification
|
||||
CALIB_ZERO_DISPARITY = 0x00400, //!< Deprecated synonim of @ref STEREO_ZERO_DISPARITY. See @ref stereoRectify.
|
||||
CALIB_USE_LU = (1 << 17), //!< use LU instead of SVD decomposition for solving. much faster but potentially less precise
|
||||
CALIB_DISABLE_SCHUR_COMPLEMENT = (1 << 18), //!< disable Schur complement (use Bouguet calibration engine)
|
||||
CALIB_USE_EXTRINSIC_GUESS = (1 << 22), //!< For stereo and multi-view calibration. Use user provided extrinsics (R, T) as initial point for optimization
|
||||
// fisheye only flags
|
||||
CALIB_RECOMPUTE_EXTRINSIC = (1 << 23), //!< For fisheye model only. Recompute board position on each calibration iteration
|
||||
@@ -875,6 +876,7 @@ fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set
|
||||
center ( imageSize is used), and focal distances are computed in a least-squares fashion.
|
||||
Note, that if intrinsic parameters are known, there is no need to use this function just to
|
||||
estimate extrinsic parameters. Use @ref solvePnP instead.
|
||||
- @ref CALIB_DISABLE_SCHUR_COMPLEMENT Disable Schur complement and use the Bouguet calibration engine (@cite Zhang2000, @cite BouguetMCT).
|
||||
- @ref CALIB_FIX_PRINCIPAL_POINT The principal point is not changed during the global
|
||||
optimization. It stays at the center or at a different location specified when
|
||||
@ref CALIB_USE_INTRINSIC_GUESS is set too.
|
||||
@@ -909,7 +911,9 @@ supplied distCoeffs matrix is used. Otherwise, it is set to 0.
|
||||
@return the overall RMS re-projection error.
|
||||
|
||||
The function estimates the intrinsic camera parameters and extrinsic parameters for each of the
|
||||
views. The algorithm is based on @cite Zhang2000 and @cite BouguetMCT . The coordinates of 3D object
|
||||
views. By default, the optimization follows a sparse bundle adjustment formulation with Schur
|
||||
complement; see @cite Triggs2000_bundle_adjustment and @cite Lourakis2009_sba for background. Use
|
||||
@ref CALIB_DISABLE_SCHUR_COMPLEMENT to switch to the Bouguet calibration engine. The coordinates of 3D object
|
||||
points and their corresponding 2D projections in each view must be specified. That may be achieved
|
||||
by using an object with known geometry and easily detectable feature points. Such an object is
|
||||
called a calibration rig or calibration pattern, and OpenCV has built-in support for a chessboard as
|
||||
@@ -932,6 +936,10 @@ The algorithm performs the following steps:
|
||||
the projected (using the current estimates for camera parameters and the poses) object points
|
||||
objectPoints. See @ref projectPoints for details.
|
||||
|
||||
- In practice, robust acquisition is essential for stable results: use multiple board poses with
|
||||
significant tilt, avoid collecting all views at a single working distance, span the expected
|
||||
working-distance range (a larger board with larger squares can help for longer distances).
|
||||
|
||||
@note
|
||||
If you use a non-square (i.e. non-N-by-N) grid and @ref findChessboardCorners for calibration,
|
||||
and @ref calibrateCamera returns bad values (zero distortion coefficients, \f$c_x\f$ and
|
||||
@@ -1017,8 +1025,8 @@ less precise and less stable in some rare cases.
|
||||
@return the overall RMS re-projection error.
|
||||
|
||||
The function estimates the intrinsic camera parameters and extrinsic parameters for each of the
|
||||
views. The algorithm is based on @cite Zhang2000, @cite BouguetMCT and @cite strobl2011iccv. See
|
||||
#calibrateCamera for other detailed explanations.
|
||||
views. The object-releasing extension follows @cite strobl2011iccv and uses the same optimization
|
||||
core as #calibrateCamera. See #calibrateCamera for other detailed explanations.
|
||||
@sa
|
||||
calibrateCamera, findChessboardCorners, solvePnP, initCameraMatrix2D, stereoCalibrate, undistort
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
#include "opencv2/core/utils/filesystem.hpp"
|
||||
|
||||
//#define SAVE_IMAGE_POINTS
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
#ifdef SAVE_IMAGE_POINTS
|
||||
|
||||
static std::vector<std::string> loadBulkImages(size_t max_images)
|
||||
{
|
||||
const std::string data_dir = findDataDirectory("perf/calib3d/bulk_n500", false);
|
||||
std::vector<std::string> image_paths;
|
||||
cv::utils::fs::glob(data_dir, "*.png", image_paths, false, false);
|
||||
if (image_paths.empty())
|
||||
cv::utils::fs::glob(data_dir, "*.jpg", image_paths, false, false);
|
||||
if (image_paths.empty())
|
||||
throw SkipTestException("No images found in perf/calib3d/bulk_n500");
|
||||
|
||||
std::sort(image_paths.begin(), image_paths.end());
|
||||
if (image_paths.size() > max_images)
|
||||
image_paths.resize(max_images);
|
||||
return image_paths;
|
||||
}
|
||||
|
||||
static std::vector<std::vector<Point2f>> buildImagePoints(const std::vector<std::string>& image_paths, const cv::Size pattern_size)
|
||||
{
|
||||
std::vector<std::vector<Point2f>> image_points;
|
||||
image_points.reserve(image_paths.size());
|
||||
|
||||
for (const auto& path : image_paths)
|
||||
{
|
||||
Mat gray = imread(path, IMREAD_GRAYSCALE);
|
||||
if (gray.empty())
|
||||
{
|
||||
printf("Can't read image: %s\n", path.c_str());
|
||||
return std::vector<std::vector<Point2f>>();
|
||||
}
|
||||
|
||||
std::vector<Point2f> corners;
|
||||
bool found = findChessboardCorners(
|
||||
gray, pattern_size, corners,
|
||||
CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE);
|
||||
|
||||
if (found)
|
||||
{
|
||||
cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1),
|
||||
TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.1));
|
||||
image_points.push_back(corners);
|
||||
}
|
||||
}
|
||||
|
||||
return image_points;
|
||||
}
|
||||
|
||||
static void saveImagePoints(const std::vector<std::vector<Point2f>>& image_points)
|
||||
{
|
||||
const std::string points_file = "bulk_n500.yaml";
|
||||
cv::FileStorage fs(points_file, cv::FileStorage::WRITE | cv::FileStorage::FORMAT_YAML);
|
||||
if (!fs.isOpened())
|
||||
{
|
||||
printf("Cannot open yaml config \"%s\" for output\n", points_file.c_str());
|
||||
}
|
||||
fs << "count" << (int)image_points.size();
|
||||
for (int i = 0; i < (int)image_points.size(); i++)
|
||||
{
|
||||
fs << cv::format("frame_%d", i) << image_points[i];
|
||||
}
|
||||
|
||||
fs.release();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static std::vector<std::vector<Point2f>> loadImagePoints()
|
||||
{
|
||||
const std::string points_file = findDataFile("perf/calib3d/bulk_n500.yaml");
|
||||
cv::FileStorage fs(points_file, cv::FileStorage::READ);
|
||||
if (!fs.isOpened())
|
||||
{
|
||||
printf("Cannot open yaml config \"%s\" for output\n", points_file.c_str());
|
||||
return std::vector<std::vector<Point2f>>();
|
||||
}
|
||||
int count = fs["count"];
|
||||
std::vector<std::vector<Point2f>> image_points(count);
|
||||
|
||||
for (int i = 0; i < (int)image_points.size(); i++)
|
||||
{
|
||||
fs[cv::format("frame_%d", i)] >> image_points[i];
|
||||
}
|
||||
|
||||
fs.release();
|
||||
|
||||
return image_points;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static std::vector<std::vector<Point3f>> buildObjectPoints(const Size& pattern_size, float square_size, size_t count)
|
||||
{
|
||||
std::vector<Point3f> board;
|
||||
board.reserve(pattern_size.area());
|
||||
|
||||
for (int y = 0; y < pattern_size.height; ++y)
|
||||
for (int x = 0; x < pattern_size.width; ++x)
|
||||
board.push_back(Point3f(x * square_size, y * square_size, 0.f));
|
||||
|
||||
std::vector<std::vector<Point3f> > object_points;
|
||||
object_points.reserve(count);
|
||||
for (size_t i = 0; i < count; i++)
|
||||
object_points.push_back(board);
|
||||
|
||||
return object_points;
|
||||
}
|
||||
|
||||
PERF_TEST(CalibrateCamera, BulkImages_N500)
|
||||
{
|
||||
// NOTE: The images archive is published at https://dl.opencv.org/data/bulk_n500.zip
|
||||
applyTestTag(CV_TEST_TAG_LONG);
|
||||
|
||||
const cv::Size pattern_size(6, 8);
|
||||
const cv::Size image_size(1280, 720);
|
||||
|
||||
#ifdef SAVE_IMAGE_POINTS
|
||||
std::vector<std::string> image_paths = loadBulkImages(500);
|
||||
std::vector<std::vector<Point2f>> image_points = buildImagePoints(image_paths, pattern_size);
|
||||
ASSERT_FALSE(image_points.empty());
|
||||
saveImagePoints(image_points);
|
||||
#else
|
||||
std::vector<std::vector<Point2f>> image_points = loadImagePoints();
|
||||
ASSERT_FALSE(image_points.empty());
|
||||
#endif
|
||||
|
||||
std::vector<std::vector<Point3f> > object_points = buildObjectPoints(pattern_size, 1.0f, image_points.size());
|
||||
|
||||
Mat camera_matrix = Mat::eye(3, 3, CV_64F);
|
||||
Mat dist_coeffs = Mat::zeros(8, 1, CV_64F);
|
||||
std::vector<Mat> rvecs;
|
||||
std::vector<Mat> tvecs;
|
||||
double rms = 0.0;
|
||||
|
||||
declare.in(image_points, object_points);
|
||||
declare.out(camera_matrix, dist_coeffs);
|
||||
declare.iterations(1);
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
camera_matrix = Mat::eye(3, 3, CV_64F);
|
||||
dist_coeffs = Mat::zeros(8, 1, CV_64F);
|
||||
rvecs.clear();
|
||||
tvecs.clear();
|
||||
rms = calibrateCamera(object_points, image_points, image_size,
|
||||
camera_matrix, dist_coeffs, rvecs, tvecs, 0);
|
||||
}
|
||||
|
||||
EXPECT_NEAR(rms, 1.768263, 1e-4);
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace opencv_test
|
||||
+1129
-15
File diff suppressed because it is too large
Load Diff
@@ -312,7 +312,7 @@ TEST_F(MultiViewTest, OneLine)
|
||||
std::vector<cv::Vec3f> board_pattern = genAsymmetricObjectPoints();
|
||||
std::vector<std::vector<cv::Vec3f>> objPoints(num_frames, board_pattern);
|
||||
|
||||
std::vector<int> flagsForIntrinsics(3, CALIB_RATIONAL_MODEL);
|
||||
std::vector<int> flagsForIntrinsics(3, CALIB_RATIONAL_MODEL | CALIB_DISABLE_SCHUR_COMPLEMENT);
|
||||
|
||||
std::vector<cv::Mat> Ks, distortions, Rs, Rs_rvec, Ts;
|
||||
double rms = calibrateMultiview(objPoints, image_points_all, image_sizes, visibility, models,
|
||||
@@ -334,7 +334,6 @@ TEST_F(MultiViewTest, OneLine)
|
||||
|
||||
TEST_F(MultiViewTest, OneLineInitialGuess)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_VERYLONG);
|
||||
const string root = cvtest::TS::ptr()->get_data_path() + "cv/cameracalibration/multiview/3cams-one-line/";
|
||||
const std::vector<std::string> cam_names = {"cam_0", "cam_1", "cam_3"};
|
||||
const std::vector<cv::Size> image_sizes = {{1920, 1080}, {1920, 1080}, {1920, 1080} };
|
||||
@@ -389,7 +388,7 @@ TEST_F(MultiViewTest, OneLineInitialGuess)
|
||||
{
|
||||
Mat K, dist;
|
||||
double mono_rms = calibrateMono(board_pattern, image_points_all[c], image_sizes[c],
|
||||
cv::CALIB_MODEL_PINHOLE, cv::CALIB_RATIONAL_MODEL,
|
||||
cv::CALIB_MODEL_PINHOLE, cv::CALIB_RATIONAL_MODEL | CALIB_DISABLE_SCHUR_COMPLEMENT,
|
||||
K, dist);
|
||||
|
||||
CV_LOG_INFO(NULL, "K:" << K);
|
||||
@@ -440,7 +439,6 @@ TEST_F(MultiViewTest, OneLineInitialGuess)
|
||||
|
||||
TEST_F(MultiViewTest, CamsToFloor)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_VERYLONG);
|
||||
const string root = cvtest::TS::ptr()->get_data_path() + "cv/cameracalibration/multiview/3cams-to-floor/";
|
||||
const std::vector<std::string> cam_names = {"cam_0", "cam_1", "cam_2"};
|
||||
std::vector<cv::Size> image_sizes = {{1920, 1080}, {1920, 1080}, {1280, 720}};
|
||||
@@ -508,7 +506,6 @@ TEST_F(MultiViewTest, CamsToFloor)
|
||||
|
||||
TEST_F(MultiViewTest, Hetero)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_VERYLONG);
|
||||
const string root = cvtest::TS::ptr()->get_data_path() + "cv/cameracalibration/multiview/3cams-hetero/";
|
||||
const std::vector<std::string> cam_names = {"cam_7", "cam_4", "cam_8"};
|
||||
std::vector<cv::Size> image_sizes = {{1920, 1080}, {1920, 1080}, {2048, 2048}};
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
#endif
|
||||
|
||||
#if defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)) && (defined(CV_CPU_COMPILE_NEON) || !defined(_MSC_VER))
|
||||
# include <Intrin.h>
|
||||
# include <intrin.h>
|
||||
# include <arm_neon.h>
|
||||
# define CV_NEON 1
|
||||
#elif defined(__ARM_NEON)
|
||||
@@ -233,7 +233,7 @@ struct VZeroUpperGuard {
|
||||
# define CV_SSE 1
|
||||
# define CV_SSE2 1
|
||||
#elif defined _WIN32 && (defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)) && (defined(CV_CPU_COMPILE_NEON) || !defined(_MSC_VER))
|
||||
# include <Intrin.h>
|
||||
# include <intrin.h>
|
||||
# include <arm_neon.h>
|
||||
# define CV_NEON 1
|
||||
#elif defined(__ARM_NEON)
|
||||
|
||||
@@ -1859,9 +1859,12 @@ inline _Tpwvec v_expand_high(const _Tpvec& a) \
|
||||
{ return _Tpwvec(__CV_CAT(intrin, _high)(a.val)); } \
|
||||
inline _Tpwvec v_load_expand(const _Tp* ptr) \
|
||||
{ \
|
||||
v128_t a = wasm_v128_load(ptr); \
|
||||
return _Tpwvec(intrin(a)); \
|
||||
}
|
||||
using lane_t = typename _Tpwvec::lane_type; \
|
||||
alignas(16) lane_t tmp[_Tpwvec::nlanes]; \
|
||||
for(int i = 0; i < _Tpwvec::nlanes; i++) \
|
||||
tmp[i] = static_cast<lane_t>(ptr[i]); \
|
||||
return _Tpwvec(wasm_v128_load(tmp)); \
|
||||
} \
|
||||
|
||||
OPENCV_HAL_IMPL_WASM_EXPAND(v_uint8x16, v_uint16x8, uchar, v128_cvtu8x16_i16x8)
|
||||
OPENCV_HAL_IMPL_WASM_EXPAND(v_int8x16, v_int16x8, schar, v128_cvti8x16_i16x8)
|
||||
@@ -1873,9 +1876,12 @@ OPENCV_HAL_IMPL_WASM_EXPAND(v_int32x4, v_int64x2, int, v128_cvti32x4_i64x2)
|
||||
#define OPENCV_HAL_IMPL_WASM_EXPAND_Q(_Tpvec, _Tp, intrin) \
|
||||
inline _Tpvec v_load_expand_q(const _Tp* ptr) \
|
||||
{ \
|
||||
v128_t a = wasm_v128_load(ptr); \
|
||||
return _Tpvec(intrin(a)); \
|
||||
}
|
||||
using lane_t = typename _Tpvec::lane_type; \
|
||||
alignas(16) lane_t tmp[_Tpvec::nlanes]; \
|
||||
for(int i = 0; i < _Tpvec::nlanes; i++) \
|
||||
tmp[i] = static_cast<lane_t>(ptr[i]); \
|
||||
return _Tpvec(wasm_v128_load(tmp)); \
|
||||
} \
|
||||
|
||||
OPENCV_HAL_IMPL_WASM_EXPAND_Q(v_uint32x4, uchar, v128_cvtu8x16_i32x4)
|
||||
OPENCV_HAL_IMPL_WASM_EXPAND_Q(v_int32x4, schar, v128_cvti8x16_i32x4)
|
||||
|
||||
@@ -29,7 +29,7 @@ PERF_TEST_P(Size_MatType, mean, TYPICAL_MATS)
|
||||
|
||||
declare.in(src, WARMUP_RNG).out(s);
|
||||
|
||||
TEST_CYCLE() s = mean(src);
|
||||
TEST_CYCLE() s = cv::mean(src);
|
||||
|
||||
SANITY_CHECK(s, 1e-5);
|
||||
}
|
||||
@@ -45,7 +45,7 @@ PERF_TEST_P(Size_MatType, mean_mask, TYPICAL_MATS)
|
||||
|
||||
declare.in(src, WARMUP_RNG).in(mask).out(s);
|
||||
|
||||
TEST_CYCLE() s = mean(src, mask);
|
||||
TEST_CYCLE() s = cv::mean(src, mask);
|
||||
|
||||
SANITY_CHECK(s, 5e-5);
|
||||
}
|
||||
|
||||
@@ -13,11 +13,330 @@
|
||||
namespace cv {
|
||||
|
||||
////////////////////////////////////// transpose /////////////////////////////////////////
|
||||
#if CV_SIMD128
|
||||
static void transpose_8bit_simd(const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz)
|
||||
{
|
||||
const int m = sz.width, n = sz.height;
|
||||
int i = 0;
|
||||
for (; i <= m - 16; i += 16)
|
||||
{
|
||||
int j = 0;
|
||||
for (; j <= n - 16; j += 16)
|
||||
{
|
||||
v_uint8x16 r0 = v_load(src + i + sstep*(j+ 0));
|
||||
v_uint8x16 r1 = v_load(src + i + sstep*(j+ 1));
|
||||
v_uint8x16 r2 = v_load(src + i + sstep*(j+ 2));
|
||||
v_uint8x16 r3 = v_load(src + i + sstep*(j+ 3));
|
||||
v_uint8x16 r4 = v_load(src + i + sstep*(j+ 4));
|
||||
v_uint8x16 r5 = v_load(src + i + sstep*(j+ 5));
|
||||
v_uint8x16 r6 = v_load(src + i + sstep*(j+ 6));
|
||||
v_uint8x16 r7 = v_load(src + i + sstep*(j+ 7));
|
||||
v_uint8x16 r8 = v_load(src + i + sstep*(j+ 8));
|
||||
v_uint8x16 r9 = v_load(src + i + sstep*(j+ 9));
|
||||
v_uint8x16 r10 = v_load(src + i + sstep*(j+10));
|
||||
v_uint8x16 r11 = v_load(src + i + sstep*(j+11));
|
||||
v_uint8x16 r12 = v_load(src + i + sstep*(j+12));
|
||||
v_uint8x16 r13 = v_load(src + i + sstep*(j+13));
|
||||
v_uint8x16 r14 = v_load(src + i + sstep*(j+14));
|
||||
v_uint8x16 r15 = v_load(src + i + sstep*(j+15));
|
||||
|
||||
v_uint8x16 t0, t1, t2, t3, t4, t5, t6, t7,
|
||||
t8, t9, t10, t11, t12, t13, t14, t15;
|
||||
|
||||
v_zip(r0, r1, t0, t1);
|
||||
v_zip(r2, r3, t2, t3);
|
||||
v_zip(r4, r5, t4, t5);
|
||||
v_zip(r6, r7, t6, t7);
|
||||
v_zip(r8, r9, t8, t9);
|
||||
v_zip(r10, r11, t10, t11);
|
||||
v_zip(r12, r13, t12, t13);
|
||||
v_zip(r14, r15, t14, t15);
|
||||
|
||||
v_uint16x8 s0, s1, s2, s3, s4, s5, s6, s7,
|
||||
s8, s9, s10, s11, s12, s13, s14, s15;
|
||||
v_zip(v_reinterpret_as_u16(t0), v_reinterpret_as_u16(t2), s0, s1);
|
||||
v_zip(v_reinterpret_as_u16(t1), v_reinterpret_as_u16(t3), s2, s3);
|
||||
v_zip(v_reinterpret_as_u16(t4), v_reinterpret_as_u16(t6), s4, s5);
|
||||
v_zip(v_reinterpret_as_u16(t5), v_reinterpret_as_u16(t7), s6, s7);
|
||||
v_zip(v_reinterpret_as_u16(t8), v_reinterpret_as_u16(t10), s8, s9);
|
||||
v_zip(v_reinterpret_as_u16(t9), v_reinterpret_as_u16(t11), s10, s11);
|
||||
v_zip(v_reinterpret_as_u16(t12), v_reinterpret_as_u16(t14), s12, s13);
|
||||
v_zip(v_reinterpret_as_u16(t13), v_reinterpret_as_u16(t15), s14, s15);
|
||||
|
||||
v_uint32x4 u0, u1, u2, u3, u4, u5, u6, u7,
|
||||
u8, u9, u10, u11, u12, u13, u14, u15;
|
||||
|
||||
v_zip(v_reinterpret_as_u32(s0), v_reinterpret_as_u32(s4), u0, u1);
|
||||
v_zip(v_reinterpret_as_u32(s1), v_reinterpret_as_u32(s5), u2, u3);
|
||||
v_zip(v_reinterpret_as_u32(s2), v_reinterpret_as_u32(s6), u4, u5);
|
||||
v_zip(v_reinterpret_as_u32(s3), v_reinterpret_as_u32(s7), u6, u7);
|
||||
v_zip(v_reinterpret_as_u32(s8), v_reinterpret_as_u32(s12), u8, u9);
|
||||
v_zip(v_reinterpret_as_u32(s9), v_reinterpret_as_u32(s13), u10, u11);
|
||||
v_zip(v_reinterpret_as_u32(s10), v_reinterpret_as_u32(s14), u12, u13);
|
||||
v_zip(v_reinterpret_as_u32(s11), v_reinterpret_as_u32(s15), u14, u15);
|
||||
|
||||
v_uint32x4 v0 = v_combine_low (u0, u8);
|
||||
v_uint32x4 v1 = v_combine_high(u0, u8);
|
||||
v_uint32x4 v2 = v_combine_low (u1, u9);
|
||||
v_uint32x4 v3 = v_combine_high(u1, u9);
|
||||
v_uint32x4 v4 = v_combine_low (u2, u10);
|
||||
v_uint32x4 v5 = v_combine_high(u2, u10);
|
||||
v_uint32x4 v6 = v_combine_low (u3, u11);
|
||||
v_uint32x4 v7 = v_combine_high(u3, u11);
|
||||
v_uint32x4 v8 = v_combine_low (u4, u12);
|
||||
v_uint32x4 v9 = v_combine_high(u4, u12);
|
||||
v_uint32x4 v10 = v_combine_low (u5, u13);
|
||||
v_uint32x4 v11 = v_combine_high(u5, u13);
|
||||
v_uint32x4 v12 = v_combine_low (u6, u14);
|
||||
v_uint32x4 v13 = v_combine_high(u6, u14);
|
||||
v_uint32x4 v14 = v_combine_low (u7, u15);
|
||||
v_uint32x4 v15 = v_combine_high(u7, u15);
|
||||
|
||||
v_store(dst + dstep*(i+ 0) + j, v_reinterpret_as_u8(v0));
|
||||
v_store(dst + dstep*(i+ 1) + j, v_reinterpret_as_u8(v1));
|
||||
v_store(dst + dstep*(i+ 2) + j, v_reinterpret_as_u8(v2));
|
||||
v_store(dst + dstep*(i+ 3) + j, v_reinterpret_as_u8(v3));
|
||||
v_store(dst + dstep*(i+ 4) + j, v_reinterpret_as_u8(v4));
|
||||
v_store(dst + dstep*(i+ 5) + j, v_reinterpret_as_u8(v5));
|
||||
v_store(dst + dstep*(i+ 6) + j, v_reinterpret_as_u8(v6));
|
||||
v_store(dst + dstep*(i+ 7) + j, v_reinterpret_as_u8(v7));
|
||||
v_store(dst + dstep*(i+ 8) + j, v_reinterpret_as_u8(v8));
|
||||
v_store(dst + dstep*(i+ 9) + j, v_reinterpret_as_u8(v9));
|
||||
v_store(dst + dstep*(i+10) + j, v_reinterpret_as_u8(v10));
|
||||
v_store(dst + dstep*(i+11) + j, v_reinterpret_as_u8(v11));
|
||||
v_store(dst + dstep*(i+12) + j, v_reinterpret_as_u8(v12));
|
||||
v_store(dst + dstep*(i+13) + j, v_reinterpret_as_u8(v13));
|
||||
v_store(dst + dstep*(i+14) + j, v_reinterpret_as_u8(v14));
|
||||
v_store(dst + dstep*(i+15) + j, v_reinterpret_as_u8(v15));
|
||||
}
|
||||
for (; j < n; j++)
|
||||
for (int k = 0; k < 16; k++)
|
||||
dst[dstep*(i+k) + j] = src[i + sstep*j + k];
|
||||
}
|
||||
for (; i < m; i++)
|
||||
for (int j = 0; j < n; j++)
|
||||
dst[dstep*i + j] = src[i + sstep*j];
|
||||
}
|
||||
|
||||
static void transpose_16bit_simd(const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz)
|
||||
{
|
||||
const ushort* src16 = reinterpret_cast<const ushort*>(src);
|
||||
ushort* dst16 = reinterpret_cast<ushort*>(dst);
|
||||
|
||||
const size_t sstep_e = sstep / sizeof(ushort);
|
||||
const size_t dstep_e = dstep / sizeof(ushort);
|
||||
|
||||
const int m = sz.width, n = sz.height;
|
||||
int i = 0;
|
||||
|
||||
for (; i <= m - 8; i += 8)
|
||||
{
|
||||
int j = 0;
|
||||
for (; j <= n - 8; j += 8)
|
||||
{
|
||||
v_uint16x8 r0 = v_load(src16 + i + sstep_e*(j+0));
|
||||
v_uint16x8 r1 = v_load(src16 + i + sstep_e*(j+1));
|
||||
v_uint16x8 r2 = v_load(src16 + i + sstep_e*(j+2));
|
||||
v_uint16x8 r3 = v_load(src16 + i + sstep_e*(j+3));
|
||||
v_uint16x8 r4 = v_load(src16 + i + sstep_e*(j+4));
|
||||
v_uint16x8 r5 = v_load(src16 + i + sstep_e*(j+5));
|
||||
v_uint16x8 r6 = v_load(src16 + i + sstep_e*(j+6));
|
||||
v_uint16x8 r7 = v_load(src16 + i + sstep_e*(j+7));
|
||||
|
||||
v_uint16x8 t0, t1, t2, t3, t4, t5, t6, t7;
|
||||
v_zip(r0, r1, t0, t1);
|
||||
v_zip(r2, r3, t2, t3);
|
||||
v_zip(r4, r5, t4, t5);
|
||||
v_zip(r6, r7, t6, t7);
|
||||
v_uint32x4 u0, u1, u2, u3, u4, u5, u6, u7;
|
||||
v_zip(v_reinterpret_as_u32(t0), v_reinterpret_as_u32(t4), u0, u1);
|
||||
v_zip(v_reinterpret_as_u32(t1), v_reinterpret_as_u32(t5), u2, u3);
|
||||
v_zip(v_reinterpret_as_u32(t2), v_reinterpret_as_u32(t6), u4, u5);
|
||||
v_zip(v_reinterpret_as_u32(t3), v_reinterpret_as_u32(t7), u6, u7);
|
||||
v_uint32x4 v0, v1, v2, v3, v4, v5, v6, v7;
|
||||
v_zip(u0, u4, v0, v1);
|
||||
v_zip(u1, u5, v2, v3);
|
||||
v_zip(u2, u6, v4, v5);
|
||||
v_zip(u3, u7, v6, v7);
|
||||
|
||||
v_store(dst16 + dstep_e*(i+0) + j, v_reinterpret_as_u16(v0));
|
||||
v_store(dst16 + dstep_e*(i+1) + j, v_reinterpret_as_u16(v1));
|
||||
v_store(dst16 + dstep_e*(i+2) + j, v_reinterpret_as_u16(v2));
|
||||
v_store(dst16 + dstep_e*(i+3) + j, v_reinterpret_as_u16(v3));
|
||||
v_store(dst16 + dstep_e*(i+4) + j, v_reinterpret_as_u16(v4));
|
||||
v_store(dst16 + dstep_e*(i+5) + j, v_reinterpret_as_u16(v5));
|
||||
v_store(dst16 + dstep_e*(i+6) + j, v_reinterpret_as_u16(v6));
|
||||
v_store(dst16 + dstep_e*(i+7) + j, v_reinterpret_as_u16(v7));
|
||||
}
|
||||
for (; j < n; j++)
|
||||
for (int k = 0; k < 8; k++)
|
||||
dst16[dstep_e*(i+k) + j] = src16[i + sstep_e*j + k];
|
||||
}
|
||||
for (; i < m; i++)
|
||||
for (int j = 0; j < n; j++)
|
||||
dst16[dstep_e*i + j] = src16[i + sstep_e*j];
|
||||
}
|
||||
|
||||
static void transpose_32bit_simd(const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz)
|
||||
{
|
||||
const uint32_t* src32 = reinterpret_cast<const uint32_t*>(src);
|
||||
uint32_t* dst32 = reinterpret_cast<uint32_t*>(dst);
|
||||
|
||||
const size_t sstep_e = sstep / sizeof(uint32_t);
|
||||
const size_t dstep_e = dstep / sizeof(uint32_t);
|
||||
|
||||
const int m = sz.width, n = sz.height;
|
||||
int i = 0;
|
||||
for (; i <= m - 4; i += 4)
|
||||
{
|
||||
int j = 0;
|
||||
for (; j <= n - 4; j += 4)
|
||||
{
|
||||
v_uint32x4 r0 = v_load(src32 + i + sstep_e*(j+0));
|
||||
v_uint32x4 r1 = v_load(src32 + i + sstep_e*(j+1));
|
||||
v_uint32x4 r2 = v_load(src32 + i + sstep_e*(j+2));
|
||||
v_uint32x4 r3 = v_load(src32 + i + sstep_e*(j+3));
|
||||
v_uint32x4 o0, o1, o2, o3;
|
||||
v_transpose4x4(r0, r1, r2, r3, o0, o1, o2, o3);
|
||||
|
||||
v_store(dst32 + dstep_e*(i+0) + j, o0);
|
||||
v_store(dst32 + dstep_e*(i+1) + j, o1);
|
||||
v_store(dst32 + dstep_e*(i+2) + j, o2);
|
||||
v_store(dst32 + dstep_e*(i+3) + j, o3);
|
||||
}
|
||||
for (; j < n; j++)
|
||||
for (int k = 0; k < 4; k++)
|
||||
dst32[dstep_e*(i+k) + j] = src32[i + sstep_e*j + k];
|
||||
}
|
||||
for (; i < m; i++)
|
||||
for (int j = 0; j < n; j++)
|
||||
dst32[dstep_e*i + j] = src32[i + sstep_e*j];
|
||||
}
|
||||
|
||||
static void transpose_48bit_simd(const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz)
|
||||
{
|
||||
const short* src16 = reinterpret_cast<const short*>(src);
|
||||
short* dst16 = reinterpret_cast<short*>(dst);
|
||||
|
||||
const size_t sstep_e = sstep / sizeof(short);
|
||||
const size_t dstep_e = dstep / sizeof(short);
|
||||
|
||||
const int m = sz.width, n = sz.height;
|
||||
int i = 0;
|
||||
|
||||
for (; i <= m - 8; i += 8)
|
||||
{
|
||||
int j = 0;
|
||||
for (; j <= n - 8; j += 8)
|
||||
{
|
||||
v_int16x8 C0_0, C1_0, C2_0;
|
||||
v_int16x8 C0_1, C1_1, C2_1;
|
||||
v_int16x8 C0_2, C1_2, C2_2;
|
||||
v_int16x8 C0_3, C1_3, C2_3;
|
||||
v_int16x8 C0_4, C1_4, C2_4;
|
||||
v_int16x8 C0_5, C1_5, C2_5;
|
||||
v_int16x8 C0_6, C1_6, C2_6;
|
||||
v_int16x8 C0_7, C1_7, C2_7;
|
||||
|
||||
v_load_deinterleave(src16 + sstep_e*(j+0) + i*3, C0_0, C1_0, C2_0);
|
||||
v_load_deinterleave(src16 + sstep_e*(j+1) + i*3, C0_1, C1_1, C2_1);
|
||||
v_load_deinterleave(src16 + sstep_e*(j+2) + i*3, C0_2, C1_2, C2_2);
|
||||
v_load_deinterleave(src16 + sstep_e*(j+3) + i*3, C0_3, C1_3, C2_3);
|
||||
v_load_deinterleave(src16 + sstep_e*(j+4) + i*3, C0_4, C1_4, C2_4);
|
||||
v_load_deinterleave(src16 + sstep_e*(j+5) + i*3, C0_5, C1_5, C2_5);
|
||||
v_load_deinterleave(src16 + sstep_e*(j+6) + i*3, C0_6, C1_6, C2_6);
|
||||
v_load_deinterleave(src16 + sstep_e*(j+7) + i*3, C0_7, C1_7, C2_7);
|
||||
|
||||
v_uint16x8 t0, t1, t2, t3, t4, t5, t6, t7;
|
||||
v_zip(v_reinterpret_as_u16(C0_0), v_reinterpret_as_u16(C0_1), t0, t1);
|
||||
v_zip(v_reinterpret_as_u16(C0_2), v_reinterpret_as_u16(C0_3), t2, t3);
|
||||
v_zip(v_reinterpret_as_u16(C0_4), v_reinterpret_as_u16(C0_5), t4, t5);
|
||||
v_zip(v_reinterpret_as_u16(C0_6), v_reinterpret_as_u16(C0_7), t6, t7);
|
||||
v_uint32x4 u0, u1, u2, u3, u4, u5, u6, u7;
|
||||
v_zip(v_reinterpret_as_u32(t0), v_reinterpret_as_u32(t4), u0, u1);
|
||||
v_zip(v_reinterpret_as_u32(t1), v_reinterpret_as_u32(t5), u2, u3);
|
||||
v_zip(v_reinterpret_as_u32(t2), v_reinterpret_as_u32(t6), u4, u5);
|
||||
v_zip(v_reinterpret_as_u32(t3), v_reinterpret_as_u32(t7), u6, u7);
|
||||
v_uint32x4 s0, s1, s2, s3, s4, s5, s6, s7;
|
||||
v_zip(u0, u4, s0, s1); v_zip(u1, u5, s2, s3);
|
||||
v_zip(u2, u6, s4, s5); v_zip(u3, u7, s6, s7);
|
||||
v_int16x8 r0_0 = v_reinterpret_as_s16(s0), r0_1 = v_reinterpret_as_s16(s1);
|
||||
v_int16x8 r0_2 = v_reinterpret_as_s16(s2), r0_3 = v_reinterpret_as_s16(s3);
|
||||
v_int16x8 r0_4 = v_reinterpret_as_s16(s4), r0_5 = v_reinterpret_as_s16(s5);
|
||||
v_int16x8 r0_6 = v_reinterpret_as_s16(s6), r0_7 = v_reinterpret_as_s16(s7);
|
||||
|
||||
v_zip(v_reinterpret_as_u16(C1_0), v_reinterpret_as_u16(C1_1), t0, t1);
|
||||
v_zip(v_reinterpret_as_u16(C1_2), v_reinterpret_as_u16(C1_3), t2, t3);
|
||||
v_zip(v_reinterpret_as_u16(C1_4), v_reinterpret_as_u16(C1_5), t4, t5);
|
||||
v_zip(v_reinterpret_as_u16(C1_6), v_reinterpret_as_u16(C1_7), t6, t7);
|
||||
v_zip(v_reinterpret_as_u32(t0), v_reinterpret_as_u32(t4), u0, u1);
|
||||
v_zip(v_reinterpret_as_u32(t1), v_reinterpret_as_u32(t5), u2, u3);
|
||||
v_zip(v_reinterpret_as_u32(t2), v_reinterpret_as_u32(t6), u4, u5);
|
||||
v_zip(v_reinterpret_as_u32(t3), v_reinterpret_as_u32(t7), u6, u7);
|
||||
v_zip(u0, u4, s0, s1); v_zip(u1, u5, s2, s3);
|
||||
v_zip(u2, u6, s4, s5); v_zip(u3, u7, s6, s7);
|
||||
v_int16x8 r1_0 = v_reinterpret_as_s16(s0), r1_1 = v_reinterpret_as_s16(s1);
|
||||
v_int16x8 r1_2 = v_reinterpret_as_s16(s2), r1_3 = v_reinterpret_as_s16(s3);
|
||||
v_int16x8 r1_4 = v_reinterpret_as_s16(s4), r1_5 = v_reinterpret_as_s16(s5);
|
||||
v_int16x8 r1_6 = v_reinterpret_as_s16(s6), r1_7 = v_reinterpret_as_s16(s7);
|
||||
|
||||
v_zip(v_reinterpret_as_u16(C2_0), v_reinterpret_as_u16(C2_1), t0, t1);
|
||||
v_zip(v_reinterpret_as_u16(C2_2), v_reinterpret_as_u16(C2_3), t2, t3);
|
||||
v_zip(v_reinterpret_as_u16(C2_4), v_reinterpret_as_u16(C2_5), t4, t5);
|
||||
v_zip(v_reinterpret_as_u16(C2_6), v_reinterpret_as_u16(C2_7), t6, t7);
|
||||
v_zip(v_reinterpret_as_u32(t0), v_reinterpret_as_u32(t4), u0, u1);
|
||||
v_zip(v_reinterpret_as_u32(t1), v_reinterpret_as_u32(t5), u2, u3);
|
||||
v_zip(v_reinterpret_as_u32(t2), v_reinterpret_as_u32(t6), u4, u5);
|
||||
v_zip(v_reinterpret_as_u32(t3), v_reinterpret_as_u32(t7), u6, u7);
|
||||
v_zip(u0, u4, s0, s1); v_zip(u1, u5, s2, s3);
|
||||
v_zip(u2, u6, s4, s5); v_zip(u3, u7, s6, s7);
|
||||
v_int16x8 r2_0 = v_reinterpret_as_s16(s0), r2_1 = v_reinterpret_as_s16(s1);
|
||||
v_int16x8 r2_2 = v_reinterpret_as_s16(s2), r2_3 = v_reinterpret_as_s16(s3);
|
||||
v_int16x8 r2_4 = v_reinterpret_as_s16(s4), r2_5 = v_reinterpret_as_s16(s5);
|
||||
v_int16x8 r2_6 = v_reinterpret_as_s16(s6), r2_7 = v_reinterpret_as_s16(s7);
|
||||
|
||||
v_store_interleave(dst16 + dstep_e*(i+0) + j*3, r0_0, r1_0, r2_0);
|
||||
v_store_interleave(dst16 + dstep_e*(i+1) + j*3, r0_1, r1_1, r2_1);
|
||||
v_store_interleave(dst16 + dstep_e*(i+2) + j*3, r0_2, r1_2, r2_2);
|
||||
v_store_interleave(dst16 + dstep_e*(i+3) + j*3, r0_3, r1_3, r2_3);
|
||||
v_store_interleave(dst16 + dstep_e*(i+4) + j*3, r0_4, r1_4, r2_4);
|
||||
v_store_interleave(dst16 + dstep_e*(i+5) + j*3, r0_5, r1_5, r2_5);
|
||||
v_store_interleave(dst16 + dstep_e*(i+6) + j*3, r0_6, r1_6, r2_6);
|
||||
v_store_interleave(dst16 + dstep_e*(i+7) + j*3, r0_7, r1_7, r2_7);
|
||||
}
|
||||
for (; j < n; j++)
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
dst16[dstep_e*(i+k) + j*3 + 0] = src16[sstep_e*j + (i+k)*3 + 0];
|
||||
dst16[dstep_e*(i+k) + j*3 + 1] = src16[sstep_e*j + (i+k)*3 + 1];
|
||||
dst16[dstep_e*(i+k) + j*3 + 2] = src16[sstep_e*j + (i+k)*3 + 2];
|
||||
}
|
||||
}
|
||||
for (; i < m; i++)
|
||||
for (int j = 0; j < n; j++)
|
||||
{
|
||||
dst16[dstep_e*i + j*3 + 0] = src16[sstep_e*j + i*3 + 0];
|
||||
dst16[dstep_e*i + j*3 + 1] = src16[sstep_e*j + i*3 + 1];
|
||||
dst16[dstep_e*i + j*3 + 2] = src16[sstep_e*j + i*3 + 2];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T> static void
|
||||
transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz )
|
||||
{
|
||||
int i=0, j, m = sz.width, n = sz.height;
|
||||
#if CV_SIMD128
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 1: transpose_8bit_simd(src, sstep, dst, dstep, sz); return;
|
||||
case 2: transpose_16bit_simd(src, sstep, dst, dstep, sz); return;
|
||||
case 4: transpose_32bit_simd(src, sstep, dst, dstep, sz); return;
|
||||
case 6: transpose_48bit_simd(src, sstep, dst, dstep, sz); return;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
|
||||
int i = 0, j, m = sz.width, n = sz.height;
|
||||
|
||||
#if CV_ENABLE_UNROLLED
|
||||
for(; i <= m - 4; i += 4 )
|
||||
@@ -146,10 +465,16 @@ static bool ocl_transpose( InputArray _src, OutputArray _dst )
|
||||
return false;
|
||||
}
|
||||
|
||||
String deviceMacro;
|
||||
if (dev.isIntel())
|
||||
deviceMacro = " -D INTEL_GPU";
|
||||
else
|
||||
deviceMacro = "";
|
||||
|
||||
ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc,
|
||||
format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d%s",
|
||||
format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d%s%s",
|
||||
ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth),
|
||||
cn, TILE_DIM, BLOCK_ROWS, rowsPerWI, inplace ? " -D INPLACE" : ""));
|
||||
cn, TILE_DIM, BLOCK_ROWS, rowsPerWI, inplace ? " -D INPLACE" : "", deviceMacro.c_str()));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
|
||||
@@ -224,9 +224,10 @@ static int sumsqr_(const T* src0, const uchar* mask, ST* sum, SQT* sqsum, int le
|
||||
v0 = (ST)src[0], v1 = (ST)src[1];
|
||||
s0 += v0; sq0 += (SQT)v0*v0;
|
||||
s1 += v1; sq1 += (SQT)v1*v1;
|
||||
v0 = (ST)src[2], v1 = (ST)src[3];
|
||||
s2 += v0; sq2 += (SQT)v0*v0;
|
||||
s3 += v1; sq3 += (SQT)v1*v1;
|
||||
ST v2, v3;
|
||||
v2 = (ST)src[2], v3 = (ST)src[3];
|
||||
s2 += v2; sq2 += (SQT)v2*v2;
|
||||
s3 += v3; sq3 += (SQT)v3*v3;
|
||||
}
|
||||
sum[k] = s0; sum[k+1] = s1;
|
||||
sum[k+2] = s2; sum[k+3] = s3;
|
||||
|
||||
@@ -53,10 +53,10 @@
|
||||
#define TSIZE ((int)sizeof(T1)*3)
|
||||
#endif
|
||||
|
||||
#ifndef INPLACE
|
||||
|
||||
#define LDS_STEP (TILE_DIM + 1)
|
||||
|
||||
#ifndef INPLACE
|
||||
|
||||
__kernel void transpose(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset)
|
||||
{
|
||||
@@ -120,6 +120,7 @@ __kernel void transpose(__global const uchar * srcptr, int src_step, int src_off
|
||||
|
||||
__kernel void transpose_inplace(__global uchar * srcptr, int src_step, int src_offset, int src_rows)
|
||||
{
|
||||
#ifdef INTEL_GPU
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1) * rowsPerWI;
|
||||
|
||||
@@ -141,6 +142,70 @@ __kernel void transpose_inplace(__global uchar * srcptr, int src_step, int src_o
|
||||
storepix(tmp, src);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int gp_x = get_group_id(0);
|
||||
int gp_y = get_group_id(1);
|
||||
int lx = get_local_id(0);
|
||||
int ly = get_local_id(1);
|
||||
|
||||
__local T tile_a[TILE_DIM * LDS_STEP];
|
||||
__local T tile_b[TILE_DIM * LDS_STEP];
|
||||
|
||||
if (gp_x > gp_y)
|
||||
{
|
||||
int x_a = gp_x * TILE_DIM + lx;
|
||||
int y_a = gp_y * TILE_DIM + ly;
|
||||
int x_b = gp_y * TILE_DIM + lx;
|
||||
int y_b = gp_x * TILE_DIM + ly;
|
||||
|
||||
// Load
|
||||
#pragma unroll
|
||||
for (int i = 0; i < TILE_DIM; i += BLOCK_ROWS)
|
||||
{
|
||||
if (y_a + i < src_rows && x_a < src_rows)
|
||||
tile_a[mad24(ly + i, LDS_STEP, lx)] =
|
||||
loadpix(srcptr + mad24(y_a + i, src_step, mad24(x_a, TSIZE, src_offset)));
|
||||
|
||||
if (y_b + i < src_rows && x_b < src_rows)
|
||||
tile_b[mad24(ly + i, LDS_STEP, lx)] =
|
||||
loadpix(srcptr + mad24(y_b + i, src_step, mad24(x_b, TSIZE, src_offset)));
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
// Store (transposed)
|
||||
#pragma unroll
|
||||
for (int i = 0; i < TILE_DIM; i += BLOCK_ROWS)
|
||||
{
|
||||
if (y_b + i < src_rows && x_b < src_rows)
|
||||
storepix(tile_a[mad24(lx, LDS_STEP, ly + i)],
|
||||
srcptr + mad24(y_b + i, src_step, mad24(x_b, TSIZE, src_offset)));
|
||||
|
||||
if (y_a + i < src_rows && x_a < src_rows)
|
||||
storepix(tile_b[mad24(lx, LDS_STEP, ly + i)],
|
||||
srcptr + mad24(y_a + i, src_step, mad24(x_a, TSIZE, src_offset)));
|
||||
}
|
||||
}
|
||||
else if (gp_x == gp_y)
|
||||
{
|
||||
int x = gp_x * TILE_DIM + lx;
|
||||
int y = gp_y * TILE_DIM + ly;
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < TILE_DIM; i += BLOCK_ROWS)
|
||||
if (y + i < src_rows && x < src_rows)
|
||||
tile_a[mad24(ly + i, LDS_STEP, lx)] =
|
||||
loadpix(srcptr + mad24(y + i, src_step, mad24(x, TSIZE, src_offset)));
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < TILE_DIM; i += BLOCK_ROWS)
|
||||
if (y + i < src_rows && x < src_rows)
|
||||
storepix(tile_a[mad24(lx, LDS_STEP, ly + i)],
|
||||
srcptr + mad24(y + i, src_step, mad24(x, TSIZE, src_offset)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // INPLACE
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
if( hasBias )
|
||||
{
|
||||
CV_Assert((size_t)biasBlobIndex < blobs.size());
|
||||
const Mat& b = blobs[weightsBlobIndex];
|
||||
const Mat& b = blobs[biasBlobIndex];
|
||||
CV_Assert(b.isContinuous() && b.type() == CV_32F && b.total() == (size_t)n);
|
||||
}
|
||||
|
||||
|
||||
@@ -514,17 +514,30 @@ public:
|
||||
|
||||
attrs.nearest_mode = ov::op::v4::Interpolate::NearestMode::ROUND_PREFER_FLOOR;
|
||||
|
||||
|
||||
std::vector<int64_t> shape = {outHeight, outWidth};
|
||||
auto out_shape = std::make_shared<ov::op::v0::Constant>(ov::element::i64, ov::Shape{2}, shape.data());
|
||||
|
||||
auto& input_shape = ieInpNode.get_shape();
|
||||
CV_Assert_N(input_shape[2] != 0, input_shape[3] != 0);
|
||||
std::vector<float> scales = {static_cast<float>(outHeight) / input_shape[2], static_cast<float>(outWidth) / input_shape[3]};
|
||||
auto scales_shape = std::make_shared<ov::op::v0::Constant>(ov::element::f32, ov::Shape{2}, scales.data());
|
||||
std::shared_ptr<ov::Node> out_shape_node;
|
||||
std::shared_ptr<ov::Node> scales_node;
|
||||
if (nodes.size() == 2)
|
||||
{
|
||||
auto& ieRefNode = nodes[1].dynamicCast<InfEngineNgraphNode>()->node;
|
||||
auto ref_shape = std::make_shared<ov::op::v3::ShapeOf>(ieRefNode, ov::element::i64);
|
||||
auto hw_indices = std::make_shared<ov::op::v0::Constant>(ov::element::i64, ov::Shape{2}, std::vector<int64_t>{2, 3});
|
||||
auto gather_axis = std::make_shared<ov::op::v0::Constant>(ov::element::i64, ov::Shape{}, 0LL);
|
||||
out_shape_node = std::make_shared<ov::op::v8::Gather>(ref_shape, hw_indices, gather_axis);
|
||||
std::vector<float> dummy_scales = {1.0f, 1.0f};
|
||||
scales_node = std::make_shared<ov::op::v0::Constant>(ov::element::f32, ov::Shape{2}, dummy_scales.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<int64_t> shape = {outHeight, outWidth};
|
||||
out_shape_node = std::make_shared<ov::op::v0::Constant>(ov::element::i64, ov::Shape{2}, shape.data());
|
||||
auto& input_shape = ieInpNode.get_shape();
|
||||
CV_Assert_N(input_shape[2] != 0, input_shape[3] != 0);
|
||||
std::vector<float> scales = {static_cast<float>(outHeight) / input_shape[2],static_cast<float>(outWidth) / input_shape[3]};
|
||||
scales_node = std::make_shared<ov::op::v0::Constant>(ov::element::f32, ov::Shape{2}, scales.data());
|
||||
}
|
||||
|
||||
auto axes = std::make_shared<ov::op::v0::Constant>(ov::element::i64, ov::Shape{2}, std::vector<int64_t>{2, 3});
|
||||
auto interp = std::make_shared<ov::op::v4::Interpolate>(ieInpNode, out_shape, scales_shape, axes, attrs);
|
||||
auto interp = std::make_shared<ov::op::v4::Interpolate>(ieInpNode, out_shape_node, scales_node, axes, attrs);
|
||||
return Ptr<BackendNode>(new InfEngineNgraphNode(interp));
|
||||
}
|
||||
#endif // HAVE_DNN_NGRAPH
|
||||
|
||||
@@ -43,8 +43,7 @@ public final class HighGui {
|
||||
|
||||
public static void imshow(String winname, Mat img) {
|
||||
if (img.empty()) {
|
||||
System.err.println("Error: Empty image in imshow");
|
||||
System.exit(-1);
|
||||
throw new IllegalArgumentException("Image is empty");
|
||||
} else {
|
||||
ImageWindow tmpWindow = windows.get(winname);
|
||||
if (tmpWindow == null) {
|
||||
@@ -113,8 +112,7 @@ public final class HighGui {
|
||||
|
||||
// If there are no windows to be shown return
|
||||
if (windows.isEmpty()) {
|
||||
System.err.println("Error: waitKey must be used after an imshow");
|
||||
System.exit(-1);
|
||||
throw new IllegalStateException("No windows created. Call imshow() first");
|
||||
}
|
||||
|
||||
// Remove the unused windows
|
||||
@@ -145,8 +143,7 @@ public final class HighGui {
|
||||
win.lbl.setIcon(icon);
|
||||
}
|
||||
} else {
|
||||
System.err.println("Error: no imshow associated with" + " namedWindow: \"" + win.name + "\"");
|
||||
System.exit(-1);
|
||||
throw new IllegalStateException("No image set for window: \"" + win.name + "\". Call imshow() first");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +155,7 @@ public final class HighGui {
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
// Set all windows as already used
|
||||
|
||||
@@ -481,6 +481,23 @@ bool PAMDecoder::readHeader()
|
||||
}
|
||||
} while (fieldtype != PAM_HEADER_ENDHDR);
|
||||
|
||||
if (selected_fmt != IMWRITE_PAM_FORMAT_NULL && flds_depth) {
|
||||
if (selected_fmt == IMWRITE_PAM_FORMAT_BLACKANDWHITE && m_channels != 1) {
|
||||
CV_Error(Error::StsError, "fmt is IMWRITE_PAM_FORMAT_BLACKANDWHITE but number of channels is not 1");
|
||||
}
|
||||
if (selected_fmt == IMWRITE_PAM_FORMAT_GRAYSCALE && m_channels != 1) {
|
||||
CV_Error(Error::StsError, "fmt is IMWRITE_PAM_FORMAT_GRAYSCALE but number of channels is not 1");
|
||||
}
|
||||
if (selected_fmt == IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA && m_channels != 2) {
|
||||
CV_Error(Error::StsError, "fmt is IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA but number of channels is not 2");
|
||||
}
|
||||
if (selected_fmt == IMWRITE_PAM_FORMAT_RGB && m_channels != 3) {
|
||||
CV_Error(Error::StsError, "fmt is IMWRITE_PAM_FORMAT_RGB but number of channels is not 3");
|
||||
}
|
||||
if (selected_fmt == IMWRITE_PAM_FORMAT_RGB_ALPHA && m_channels != 4) {
|
||||
CV_Error(Error::StsError, "fmt is IMWRITE_PAM_FORMAT_RGB_ALPHA but number of channels is not 4");
|
||||
}
|
||||
}
|
||||
if (flds_endhdr && flds_height && flds_width && flds_depth && flds_maxval)
|
||||
{
|
||||
if (selected_fmt == IMWRITE_PAM_FORMAT_NULL)
|
||||
|
||||
@@ -23,24 +23,20 @@ public class Utils {
|
||||
public static String exportResource(Context context, int resourceId, String dirname) {
|
||||
String fullname = context.getResources().getString(resourceId);
|
||||
String resName = fullname.substring(fullname.lastIndexOf("/") + 1);
|
||||
try {
|
||||
InputStream is = context.getResources().openRawResource(resourceId);
|
||||
try (InputStream is = context.getResources().openRawResource(resourceId)) {
|
||||
File resDir = context.getDir(dirname, Context.MODE_PRIVATE);
|
||||
File resFile = new File(resDir, resName);
|
||||
|
||||
FileOutputStream os = new FileOutputStream(resFile);
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
try (FileOutputStream os = new FileOutputStream(resFile)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
is.close();
|
||||
os.close();
|
||||
|
||||
return resFile.getAbsolutePath();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new CvException("Failed to export resource " + resName
|
||||
+ ". Exception thrown: " + e);
|
||||
}
|
||||
@@ -53,19 +49,22 @@ public class Utils {
|
||||
|
||||
public static Mat loadResource(Context context, int resourceId, int flags) throws IOException
|
||||
{
|
||||
InputStream is = context.getResources().openRawResource(resourceId);
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream(is.available());
|
||||
byte[] data;
|
||||
int dataLength;
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
try (InputStream is = context.getResources().openRawResource(resourceId);
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream(is.available())) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
data = os.toByteArray();
|
||||
dataLength = os.size();
|
||||
}
|
||||
is.close();
|
||||
|
||||
Mat encoded = new Mat(1, os.size(), CvType.CV_8U);
|
||||
encoded.put(0, 0, os.toByteArray());
|
||||
os.close();
|
||||
Mat encoded = new Mat(1, dataLength, CvType.CV_8U);
|
||||
encoded.put(0, 0, data);
|
||||
|
||||
Mat decoded = Imgcodecs.imdecode(encoded, flags);
|
||||
encoded.release();
|
||||
|
||||
@@ -209,9 +209,9 @@ bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo& info)
|
||||
if (ismultichannel)
|
||||
{
|
||||
int channels = ndims >= 1 ? (int)_sizes[ndims - 1] : 1;
|
||||
if (channels > CV_CN_MAX)
|
||||
if (channels < 1 || channels > CV_CN_MAX)
|
||||
{
|
||||
failmsg("%s unable to wrap channels, too high (%d > CV_CN_MAX=%d)", info.name, (int)channels, (int)CV_CN_MAX);
|
||||
failmsg("%s unable to wrap channels, invalid count (%d, must be in [1, %d])", info.name, (int)channels, (int)CV_CN_MAX);
|
||||
return false;
|
||||
}
|
||||
ndims--;
|
||||
|
||||
@@ -89,6 +89,23 @@ try:
|
||||
print(res1)
|
||||
|
||||
|
||||
def test_mat_wrap_channels_zero(self):
|
||||
# Passing a 0-channel array must raise cv.error, not segfault.
|
||||
data = np.zeros((100, 100, 0), dtype=np.uint8)
|
||||
|
||||
with self.assertRaises(cv.error):
|
||||
cv.resize(data, (200, 200)) # channels=0 -> invalid, must not segfault
|
||||
|
||||
with self.assertRaises(cv.error):
|
||||
mat_data = cv.Mat(data, wrap_channels=True) # unable to wrap channels, invalid count (0)
|
||||
cv.utils.dumpInputArray(mat_data)
|
||||
|
||||
# Verify that channels=1 (lower bound) still works correctly
|
||||
data_1ch = np.zeros((100, 100, 1), dtype=np.uint8)
|
||||
mat_1ch = cv.Mat(data_1ch, wrap_channels=True)
|
||||
res = cv.utils.dumpInputArray(mat_1ch)
|
||||
self.assertIn("CV_8UC1", res)
|
||||
|
||||
def test_ufuncs(self):
|
||||
data = np.arange(10)
|
||||
mat_data = cv.Mat(data)
|
||||
|
||||
@@ -138,7 +138,7 @@ enum VideoCaptureProperties {
|
||||
CAP_PROP_FOURCC =6, //!< 4-character code of codec. see VideoWriter::fourcc .
|
||||
CAP_PROP_FRAME_COUNT =7, //!< Number of frames in the video file.
|
||||
CAP_PROP_FORMAT =8, //!< Format of the %Mat objects (see Mat::type()) returned by VideoCapture::retrieve().
|
||||
//!< Set value -1 to fetch undecoded RAW video streams (as Mat 8UC1).
|
||||
//!< Set value -1 to fetch undecoded RAW video streams (as Mat 8UC1). Default is 8UC3. FFmpeg backend supports 8UC4 with alpha, if it's available.
|
||||
CAP_PROP_MODE =9, //!< Backend-specific value indicating the current capture mode.
|
||||
CAP_PROP_BRIGHTNESS =10, //!< Brightness of the image (only for those cameras that support).
|
||||
CAP_PROP_CONTRAST =11, //!< Contrast of the image (only for cameras).
|
||||
@@ -226,6 +226,8 @@ enum VideoWriterProperties {
|
||||
VIDEOWRITER_PROP_KEY_FLAG = 11, //!< Set to non-zero to signal that the following frames are key frames or zero if not, when encapsulating raw video (\ref VIDEOWRITER_PROP_RAW_VIDEO != 0). FFmpeg back-end only.
|
||||
VIDEOWRITER_PROP_PTS = 12, //!< Specifies the frame presentation timestamp for each frame using the FPS time base. This property is **only** necessary when encapsulating **externally** encoded video where the decoding order differs from the presentation order, such as in GOP patterns with bi-directional B-frames. The value should be provided by your external encoder and for video sources with fixed frame rates it is equivalent to dividing the current frame's presentation time (\ref CAP_PROP_POS_MSEC) by the frame duration (1000.0 / VideoCapture::get(\ref CAP_PROP_FPS)). It can be queried from the resulting encapsulated video file using VideoCapture::get(\ref CAP_PROP_PTS). FFmpeg back-end only.
|
||||
VIDEOWRITER_PROP_DTS_DELAY = 13, //!< Specifies the maximum difference between presentation (pts) and decompression timestamps (dts) using the FPS time base. This property is necessary **only** when encapsulating **externally** encoded video where the decoding order differs from the presentation order, such as in GOP patterns with bi-directional B-frames. The value should be calculated based on the specific GOP pattern used during encoding. For example, in a GOP with presentation order IBP and decoding order IPB, this value would be 1, as the B-frame is the second frame presented but the third to be decoded. It can be queried from the resulting encapsulated video file using VideoCapture::get(\ref CAP_PROP_DTS_DELAY). Non-zero values usually imply the stream is encoded using B-frames. FFmpeg back-end only.
|
||||
VIDEOWRITER_PROP_COLOR_SPACE = 14, //!< (**open-only**) GStreamer backend only. Pixel format for the encoding profile. Default is "I420". Other values: "NV12", "BGRx". See GStreamer raw video formats for more options.
|
||||
VIDEOWRITER_PROP_ENABLE_ALPHA = 15, //!< (**open-only**) FFmpeg backend only. Defines that input frames contain alpha channel.
|
||||
#ifndef CV_DOXYGEN
|
||||
CV__VIDEOWRITER_PROP_LATEST
|
||||
#endif
|
||||
|
||||
@@ -612,6 +612,7 @@ struct CvCapture_FFMPEG
|
||||
bool rawModeInitialized;
|
||||
bool rawSeek;
|
||||
bool convertRGB;
|
||||
bool enableAlpha;
|
||||
AVPacket packet_filtered;
|
||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(58, 20, 100)
|
||||
AVBSFContext* bsfc;
|
||||
@@ -669,6 +670,7 @@ void CvCapture_FFMPEG::init()
|
||||
rawModeInitialized = false;
|
||||
rawSeek = false;
|
||||
convertRGB = true;
|
||||
enableAlpha = false;
|
||||
memset(&packet_filtered, 0, sizeof(packet_filtered));
|
||||
av_init_packet(&packet_filtered);
|
||||
bsfc = NULL;
|
||||
@@ -1085,9 +1087,10 @@ bool CvCapture_FFMPEG::open(const char* _filename, int index, const Ptr<IStreamR
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO/FFMPEG: BGR conversion turned OFF, decoded frame will be "
|
||||
"returned in its original format. "
|
||||
"Multiplanar formats are not supported by the backend. "
|
||||
"Only GRAY8/GRAY16LE pixel formats have been tested. "
|
||||
"Only GRAY8/GRAY16LE/RGBA pixel formats have been tested. "
|
||||
"Use at your own risk.");
|
||||
}
|
||||
|
||||
if (params.has(CAP_PROP_FORMAT))
|
||||
{
|
||||
int value = params.get<int>(CAP_PROP_FORMAT);
|
||||
@@ -1098,8 +1101,19 @@ bool CvCapture_FFMPEG::open(const char* _filename, int index, const Ptr<IStreamR
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: CAP_PROP_FORMAT parameter value is invalid/unsupported: " << value);
|
||||
return false;
|
||||
if (value == CV_8UC3)
|
||||
{
|
||||
enableAlpha = false;
|
||||
}
|
||||
if (value == CV_8UC4)
|
||||
{
|
||||
enableAlpha = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: CAP_PROP_FORMAT parameter value is invalid/unsupported: " << value);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!rawMode) {
|
||||
@@ -1879,9 +1893,12 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step,
|
||||
<< ", primaries: " << av_color_primaries_name(sw_picture->color_primaries)
|
||||
<< ", transfer: " << av_color_transfer_name(sw_picture->color_trc)
|
||||
);
|
||||
const AVPixelFormat result_format = convertRGB ? AV_PIX_FMT_BGR24 : (AVPixelFormat)sw_picture->format;
|
||||
|
||||
const AVPixelFormat color_format = enableAlpha ? AV_PIX_FMT_BGRA : AV_PIX_FMT_BGR24;
|
||||
const AVPixelFormat result_format = convertRGB ? color_format : (AVPixelFormat)sw_picture->format;
|
||||
switch (result_format)
|
||||
{
|
||||
case AV_PIX_FMT_BGRA: *depth = CV_8U; *cn = 4; break;
|
||||
case AV_PIX_FMT_BGR24: *depth = CV_8U; *cn = 3; break;
|
||||
case AV_PIX_FMT_GRAY8: *depth = CV_8U; *cn = 1; break;
|
||||
case AV_PIX_FMT_GRAY16LE: *depth = CV_16U; *cn = 1; break;
|
||||
@@ -2122,6 +2139,12 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const
|
||||
case CAP_PROP_FORMAT:
|
||||
if (rawMode)
|
||||
return -1;
|
||||
else if (!convertRGB)
|
||||
return CV_8UC1;
|
||||
else if (enableAlpha)
|
||||
return CV_8UC4;
|
||||
else
|
||||
return CV_8UC3;
|
||||
break;
|
||||
case CAP_PROP_CONVERT_RGB:
|
||||
return convertRGB;
|
||||
@@ -2365,8 +2388,20 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value )
|
||||
seek((int64_t)(value*ic->duration));
|
||||
return true;
|
||||
case CAP_PROP_FORMAT:
|
||||
if (!convertRGB)
|
||||
return false;
|
||||
if (value == -1)
|
||||
return setRaw();
|
||||
else if (value == CV_8UC3)
|
||||
{
|
||||
enableAlpha = false;
|
||||
return true;
|
||||
}
|
||||
else if (value == CV_8UC4)
|
||||
{
|
||||
enableAlpha = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case CAP_PROP_CONVERT_RGB:
|
||||
convertRGB = (value != 0);
|
||||
@@ -2775,6 +2810,12 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (input_pix_fmt == AV_PIX_FMT_BGRA) {
|
||||
if (cn != 4) {
|
||||
CV_LOG_WARNING(NULL, "write frame skipped - expected 4 channels but got " << cn);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (input_pix_fmt == AV_PIX_FMT_GRAY8 || input_pix_fmt == AV_PIX_FMT_GRAY16LE) {
|
||||
if (cn != 1) {
|
||||
CV_LOG_WARNING(NULL, "write frame skipped - expected 1 channel but got " << cn);
|
||||
@@ -3151,6 +3192,8 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
||||
use_opencl = params.get<int>(VIDEOWRITER_PROP_HW_ACCELERATION_USE_OPENCL);
|
||||
}
|
||||
|
||||
bool enable_alpha = params.get<bool>(VIDEOWRITER_PROP_ENABLE_ALPHA, false);
|
||||
|
||||
if (params.warnUnusedParameters())
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: unsupported parameters in VideoWriter, see logger INFO channel for details");
|
||||
@@ -3185,7 +3228,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
||||
{
|
||||
switch (depth)
|
||||
{
|
||||
case CV_8U: input_pix_fmt = AV_PIX_FMT_BGR24; break;
|
||||
case CV_8U: input_pix_fmt = enable_alpha ? AV_PIX_FMT_BGRA : AV_PIX_FMT_BGR24; break;
|
||||
default:
|
||||
CV_LOG_WARNING(NULL, "Unsupported input depth for color image: " << depth);
|
||||
return false;
|
||||
@@ -3387,7 +3430,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
||||
break;
|
||||
default:
|
||||
// good for lossy formats, MPEG, etc.
|
||||
codec_pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
codec_pix_fmt = enable_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -2512,25 +2512,43 @@ bool CvVideoWriter_GStreamer::open( const std::string &filename, int fourcc,
|
||||
CV_WARN("OpenCV backend does not support this file type (extension): " << filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
//create pipeline elements
|
||||
encodebin.reset(gst_element_factory_make("encodebin", NULL));
|
||||
|
||||
if (!encodebin)
|
||||
{
|
||||
CV_WARN("GStreamer: cannot create encodebin element");
|
||||
return false;
|
||||
}
|
||||
GSafePtr<GstCaps> containercaps;
|
||||
GSafePtr<GstEncodingContainerProfile> containerprofile;
|
||||
GSafePtr<GstEncodingVideoProfile> videoprofile;
|
||||
|
||||
containercaps.attach(gst_caps_from_string(mime));
|
||||
|
||||
//create encodebin profile
|
||||
containerprofile.attach(gst_encoding_container_profile_new("container", "container", containercaps.get(), NULL));
|
||||
videoprofile.reset(gst_encoding_video_profile_new(videocaps.get(), NULL, NULL, 1));
|
||||
gst_encoding_container_profile_add_profile(containerprofile.get(), (GstEncodingProfile*)videoprofile.get());
|
||||
|
||||
unsigned int colorspace_fourcc = (unsigned int)params.get(VIDEOWRITER_PROP_COLOR_SPACE, CV_FOURCC('I', '4', '2', '0'));
|
||||
const char* colorspace = gst_video_format_to_string(gst_video_format_from_fourcc(colorspace_fourcc));
|
||||
GSafePtr<GstCaps> prof_caps;
|
||||
std::string caps_str = std::string("video/x-raw, format=") + std::string(colorspace);
|
||||
prof_caps.attach(gst_caps_from_string(caps_str.c_str()));
|
||||
videoprofile.attach(gst_encoding_video_profile_new(prof_caps.get(), NULL, NULL, 1));
|
||||
// Transfer ownership to the container profile
|
||||
gst_encoding_container_profile_add_profile(
|
||||
containerprofile.get(),
|
||||
(GstEncodingProfile*)videoprofile.detach()
|
||||
);
|
||||
g_object_set(G_OBJECT(encodebin.get()), "profile", containerprofile.get(), NULL);
|
||||
|
||||
source.reset(gst_element_factory_make("appsrc", NULL));
|
||||
if (!source)
|
||||
{
|
||||
CV_WARN("GStreamer: cannot create appsrc element");
|
||||
return false;
|
||||
}
|
||||
file.reset(gst_element_factory_make("filesink", NULL));
|
||||
if (!file)
|
||||
{
|
||||
CV_WARN("GStreamer: cannot create filesink element");
|
||||
return false;
|
||||
}
|
||||
g_object_set(G_OBJECT(file.get()), "location", (const char*)filename.c_str(), NULL);
|
||||
}
|
||||
|
||||
@@ -2709,21 +2727,22 @@ void CvVideoWriter_GStreamer::write(InputArray image)
|
||||
|
||||
Mat imageMat = image.getMat();
|
||||
const size_t buf_size = imageMat.total() * imageMat.elemSize();
|
||||
duration = ((double)1/framerate) * GST_SECOND;
|
||||
timestamp = num_frames * duration;
|
||||
duration = gst_util_uint64_scale_int(GST_SECOND, 1, framerate);
|
||||
timestamp = gst_util_uint64_scale_int(num_frames, GST_SECOND, framerate);
|
||||
|
||||
//gst_app_src_push_buffer takes ownership of the buffer, so we need to supply it a copy
|
||||
GstBuffer *buffer = gst_buffer_new_allocate(NULL, buf_size, NULL);
|
||||
GstMapInfo info;
|
||||
gst_buffer_map(buffer, &info, (GstMapFlags)GST_MAP_READ);
|
||||
memcpy(info.data, (guint8*)imageMat.data, buf_size);
|
||||
gst_buffer_unmap(buffer, &info);
|
||||
if (gst_buffer_map(buffer, &info, (GstMapFlags)GST_MAP_WRITE)) {
|
||||
memcpy(info.data, (guint8*)imageMat.data, buf_size);
|
||||
gst_buffer_unmap(buffer, &info);
|
||||
}
|
||||
GST_BUFFER_DURATION(buffer) = duration;
|
||||
GST_BUFFER_PTS(buffer) = timestamp;
|
||||
GST_BUFFER_DTS(buffer) = timestamp;
|
||||
//set the current number in the frame
|
||||
GST_BUFFER_OFFSET(buffer) = num_frames;
|
||||
|
||||
GST_BUFFER_OFFSET_END(buffer) = num_frames + 1;
|
||||
ret = gst_app_src_push_buffer(GST_APP_SRC(source.get()), buffer);
|
||||
if (ret != GST_FLOW_OK)
|
||||
{
|
||||
|
||||
@@ -1030,6 +1030,75 @@ inline static std::string videoio_ffmpeg_mismatch_name_printer(const testing::Te
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, videoio_ffmpeg_channel_mismatch, testing::ValuesIn(mismatch_cases), videoio_ffmpeg_mismatch_name_printer);
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
typedef tuple<string, string> AlphaChannelParams;
|
||||
typedef testing::TestWithParam< AlphaChannelParams > videoio_ffmpeg_alpha_channel;
|
||||
|
||||
// New feature in https://github.com/opencv/opencv/pull/28751 requires FFmpeg wrapper rebuild on Windows
|
||||
TEST_P(videoio_ffmpeg_alpha_channel, write_read)
|
||||
{
|
||||
if (!videoio_registry::hasBackend(CAP_FFMPEG))
|
||||
throw SkipTestException("FFmpeg backend was not found");
|
||||
|
||||
const int fourcc = fourccFromString(get<0>(GetParam()));
|
||||
const string filename = "video_with_alpha_channel." + get<1>(GetParam());
|
||||
cv::VideoWriter writer(filename, cv::CAP_FFMPEG, fourcc, 1, Size(320, 240),
|
||||
{VIDEOWRITER_PROP_IS_COLOR, 1,
|
||||
VIDEOWRITER_PROP_ENABLE_ALPHA, 1});
|
||||
|
||||
ASSERT_TRUE(writer.isOpened());
|
||||
|
||||
for (int i = 0; i < 10; i ++)
|
||||
{
|
||||
cv::Mat frame;
|
||||
cv::Mat gray_frame(240, 320, CV_8UC1, cv::Scalar::all(0));
|
||||
gray_frame(Rect(i*10, i*10, i*10, i*10)).setTo(255);
|
||||
cv::Mat channels[4] = {gray_frame, gray_frame, gray_frame, gray_frame};
|
||||
cv::merge(channels, 4, frame);
|
||||
writer.write(frame);
|
||||
}
|
||||
|
||||
writer.release();
|
||||
|
||||
cv::VideoCapture cap(filename, cv::CAP_FFMPEG, {cv::CAP_PROP_FORMAT, CV_8UC4});
|
||||
ASSERT_TRUE(cap.isOpened());
|
||||
ASSERT_EQ(10, cap.get(cv::CAP_PROP_FRAME_COUNT));
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
cv::Mat frame;
|
||||
cap >> frame;
|
||||
EXPECT_EQ(4, frame.channels());
|
||||
EXPECT_EQ(320, frame.cols);
|
||||
EXPECT_EQ(240, frame.rows);
|
||||
EXPECT_EQ(0, frame.data[0]);
|
||||
EXPECT_EQ(0, frame.data[1]);
|
||||
EXPECT_EQ(0, frame.data[2]);
|
||||
EXPECT_EQ(0, frame.data[3]);
|
||||
|
||||
cv::Mat channels[4];
|
||||
cv::split(frame, channels);
|
||||
int g_non_zero = cv::countNonZero(channels[1]);
|
||||
int alpha_non_zero = cv::countNonZero(channels[3]);
|
||||
|
||||
EXPECT_EQ(g_non_zero, alpha_non_zero);
|
||||
}
|
||||
remove(filename.c_str());
|
||||
}
|
||||
|
||||
AlphaChannelParams alpha_params[] =
|
||||
{
|
||||
make_tuple("FFV1", "mkv"),
|
||||
make_tuple("FFV1", "avi")
|
||||
// webm and hevc formats are disable as require fresh FFmpeg
|
||||
//make_tuple("VP90", "webm")
|
||||
//make_tuple("hevc", "mp4")
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, videoio_ffmpeg_alpha_channel, testing::ValuesIn(alpha_params));
|
||||
#endif
|
||||
|
||||
// PR: https://github.com/opencv/opencv/pull/27523
|
||||
// TODO: Enable the tests back on Windows after FFmpeg plugin rebuild
|
||||
#ifndef _WIN32
|
||||
|
||||
Reference in New Issue
Block a user