mirror of
https://github.com/opencv/opencv.git
synced 2026-07-26 22:03:04 +04:00
Compare commits
140 Commits
5.0.0-alpha
...
4.11.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 31b0eeea0b | |||
| d2704548b4 | |||
| 198f23890e | |||
| 66ffeae4b1 | |||
| 38b86591ba | |||
| cb959b3915 | |||
| e34eff9ab2 | |||
| 0dfd2b3628 | |||
| 4b35101d55 | |||
| d5087a2bd6 | |||
| 0331af01ae | |||
| 0e3d71b0e0 | |||
| 9b85ab0a63 | |||
| d86387347d | |||
| 56dd9d51b1 | |||
| fc994a6ae8 | |||
| 2aee94752a | |||
| 904dbe9555 | |||
| 3d7eb55f75 | |||
| ad36f68500 | |||
| 3e534bb7c8 | |||
| ff18c9cc79 | |||
| a6f72f813d | |||
| f65006eee1 | |||
| b4d0325666 | |||
| 0538e64b13 | |||
| 9e8b9a0ebb | |||
| 845616d82c | |||
| 5e1eed5026 | |||
| ffd0548651 | |||
| 2f0035b23f | |||
| 12963ea699 | |||
| f2878eb337 | |||
| 4d26e16af8 | |||
| 1db982780f | |||
| c803aa2ddd | |||
| 269ff8cd83 | |||
| d2264d5868 | |||
| f15fa21c6b | |||
| 8bc65a1d13 | |||
| d39aae6bdf | |||
| 9c33baebbd | |||
| 1b48eafe48 | |||
| b31f7694c5 | |||
| 94bccbecc0 | |||
| aeb7a9b383 | |||
| 707ab39454 | |||
| c64fe91ff4 | |||
| 4c7ea70051 | |||
| 09892c9d17 | |||
| e9982e856f | |||
| 745a12c03b | |||
| 96d6395a6d | |||
| fe649f4adb | |||
| f106866d3e | |||
| 0756dbfe3d | |||
| b42075f3e2 | |||
| 1399672a83 | |||
| a2ce9e1bac | |||
| ec2208f5f7 | |||
| 4efd52f676 | |||
| aa52dafc90 | |||
| d9a139f9e8 | |||
| 0903061589 | |||
| f3d9d56ebe | |||
| 8ffc4a6bd5 | |||
| b53fa94745 | |||
| 6a0affdbce | |||
| 3073ba28cc | |||
| 5baca5275e | |||
| d037b40faa | |||
| 60d35d1bd5 | |||
| cdad0b7027 | |||
| ebf3c400d2 | |||
| 59f762b2f0 | |||
| 537a2566cf | |||
| 9f64f021de | |||
| e747ed11cb | |||
| 5cd448377a | |||
| 79d019b4f1 | |||
| 428d93114f | |||
| 914a83fa0c | |||
| a628417f2a | |||
| 773bd1a90a | |||
| 3fbaad36d7 | |||
| 7c0c9e1e55 | |||
| 874e57512e | |||
| 1fe9dd0c3b | |||
| d369cf6d50 | |||
| 1c28a98b34 | |||
| 23f6a9ee3e | |||
| 3899a060a3 | |||
| 7ddc02907e | |||
| d77abeddd0 | |||
| 59b9681af6 | |||
| 2e21e11318 | |||
| e0001903ce | |||
| a8f4019932 | |||
| dbb330d7be | |||
| 0ca98d437b | |||
| 51ec7fedaf | |||
| 260f511dfb | |||
| 1a1b1901e8 | |||
| a4c8d318e6 | |||
| 03f90aaf85 | |||
| 71581d9c97 | |||
| 25fe85bbbb | |||
| 42be822c1d | |||
| 1d4110884b | |||
| dc8a9d5d3d | |||
| 5ef062343c | |||
| d85c13bcbb | |||
| 0dfc5d416f | |||
| 4ade7931e1 | |||
| 0a2669daba | |||
| 3a8d7ec75a | |||
| 1db93911ae | |||
| 1f2e7adb4b | |||
| acdb707ba4 | |||
| 082cd7a74e | |||
| 7fbf3c1fec | |||
| ed9d64c9d3 | |||
| 646e87c728 | |||
| 7edfb57f5a | |||
| 3d91d75f1a | |||
| 23fcea0d33 | |||
| 03cedee0b0 | |||
| 8897002fcc | |||
| 31d04f8fd9 | |||
| c58b6bf11f | |||
| 89c19f1f1a | |||
| f4db63ca71 | |||
| 5f1b05af0e | |||
| 6eaa77461e | |||
| 96dab6ba71 | |||
| e953fcfaa4 | |||
| bef3585245 | |||
| b385767c1c | |||
| d6fe289a79 | |||
| fab419a484 |
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
if(HAVE_FASTCV)
|
||||
set(FASTCV_HAL_VERSION 0.0.1 CACHE INTERNAL "")
|
||||
set(FASTCV_HAL_LIBRARIES "fastcv_hal" CACHE INTERNAL "")
|
||||
set(FASTCV_HAL_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" CACHE INTERNAL "")
|
||||
set(FASTCV_HAL_HEADERS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/fastcv_hal_core.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/fastcv_hal_imgproc.hpp"
|
||||
CACHE INTERNAL "")
|
||||
|
||||
file(GLOB FASTCV_HAL_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
|
||||
|
||||
add_library(fastcv_hal STATIC ${FASTCV_HAL_FILES})
|
||||
|
||||
target_include_directories(fastcv_hal PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/modules/core/include
|
||||
${CMAKE_SOURCE_DIR}/modules/imgproc/include
|
||||
${FASTCV_HAL_INCLUDE_DIRS} ${FastCV_INCLUDE_PATH})
|
||||
|
||||
target_link_libraries(fastcv_hal PUBLIC ${FASTCV_LIBRARY})
|
||||
|
||||
set_target_properties(fastcv_hal PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH})
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
ocv_install_target(fastcv_hal EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev)
|
||||
endif()
|
||||
|
||||
if(ENABLE_SOLUTION_FOLDERS)
|
||||
set_target_properties(fastcv_hal PROPERTIES FOLDER "3rdparty")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "FastCV is not available, disabling related HAL")
|
||||
endif(HAVE_FASTCV)
|
||||
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
function(download_fastcv root_dir)
|
||||
|
||||
# Commit SHA in the opencv_3rdparty repo
|
||||
set(FASTCV_COMMIT "dc5d58018f3af915a8d209386d2c58c0501c0f2c")
|
||||
|
||||
# Define actual FastCV versions
|
||||
if(ANDROID)
|
||||
if(AARCH64)
|
||||
message(STATUS "Download FastCV for Android aarch64")
|
||||
set(FCV_PACKAGE_NAME "fastcv_android_aarch64_2024_12_11.tgz")
|
||||
set(FCV_PACKAGE_HASH "9dac41e86597305f846212dae31a4a88")
|
||||
else()
|
||||
message(STATUS "Download FastCV for Android armv7")
|
||||
set(FCV_PACKAGE_NAME "fastcv_android_arm32_2024_12_11.tgz")
|
||||
set(FCV_PACKAGE_HASH "fe2d30334180b17e3031eee92aac43b6")
|
||||
endif()
|
||||
elseif(UNIX AND NOT APPLE AND NOT IOS AND NOT XROS)
|
||||
if(AARCH64)
|
||||
set(FCV_PACKAGE_NAME "fastcv_linux_aarch64_2024_12_11.tgz")
|
||||
set(FCV_PACKAGE_HASH "7b33ad833e6f15ab6d4ec64fa3c17acd")
|
||||
else()
|
||||
message("FastCV: fastcv lib for 32-bit Linux is not supported for now!")
|
||||
endif()
|
||||
endif(ANDROID)
|
||||
|
||||
# Download Package
|
||||
set(OPENCV_FASTCV_URL "https://raw.githubusercontent.com/opencv/opencv_3rdparty/${FASTCV_COMMIT}/fastcv/")
|
||||
|
||||
ocv_download( FILENAME ${FCV_PACKAGE_NAME}
|
||||
HASH ${FCV_PACKAGE_HASH}
|
||||
URL ${OPENCV_FASTCV_URL}
|
||||
DESTINATION_DIR ${root_dir}
|
||||
ID FASTCV
|
||||
STATUS res
|
||||
UNPACK
|
||||
RELATIVE_URL)
|
||||
if(res)
|
||||
set(HAVE_FASTCV TRUE CACHE BOOL "FastCV status")
|
||||
else()
|
||||
message(WARNING "FastCV: package download failed!")
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_HAL_CORE_HPP_INCLUDED
|
||||
#define OPENCV_FASTCV_HAL_CORE_HPP_INCLUDED
|
||||
|
||||
#include <opencv2/core/base.hpp>
|
||||
|
||||
#undef cv_hal_lut
|
||||
#define cv_hal_lut fastcv_hal_lut
|
||||
#undef cv_hal_normHammingDiff8u
|
||||
#define cv_hal_normHammingDiff8u fastcv_hal_normHammingDiff8u
|
||||
#undef cv_hal_mul8u16u
|
||||
#define cv_hal_mul8u16u fastcv_hal_mul8u16u
|
||||
#undef cv_hal_sub8u32f
|
||||
#define cv_hal_sub8u32f fastcv_hal_sub8u32f
|
||||
#undef cv_hal_transpose2d
|
||||
#define cv_hal_transpose2d fastcv_hal_transpose2d
|
||||
#undef cv_hal_meanStdDev
|
||||
#define cv_hal_meanStdDev fastcv_hal_meanStdDev
|
||||
#undef cv_hal_flip
|
||||
#define cv_hal_flip fastcv_hal_flip
|
||||
#undef cv_hal_rotate90
|
||||
#define cv_hal_rotate90 fastcv_hal_rotate
|
||||
#undef cv_hal_addWeighted8u
|
||||
#define cv_hal_addWeighted8u fastcv_hal_addWeighted8u
|
||||
#undef cv_hal_mul8u
|
||||
#define cv_hal_mul8u fastcv_hal_mul8u
|
||||
#undef cv_hal_mul16s
|
||||
#define cv_hal_mul16s fastcv_hal_mul16s
|
||||
#undef cv_hal_mul32f
|
||||
#define cv_hal_mul32f fastcv_hal_mul32f
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look-up table transform of an array.
|
||||
/// @param src_data Source image data
|
||||
/// @param src_step Source image step
|
||||
/// @param src_type Source image type
|
||||
/// @param lut_data Pointer to lookup table
|
||||
/// @param lut_channel_size Size of each channel in bytes
|
||||
/// @param lut_channels Number of channels in lookup table
|
||||
/// @param dst_data Destination data
|
||||
/// @param dst_step Destination step
|
||||
/// @param width Width of images
|
||||
/// @param height Height of images
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_lut(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
size_t src_type,
|
||||
const uchar* lut_data,
|
||||
size_t lut_channel_size,
|
||||
size_t lut_channels,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Hamming distance between two vectors
|
||||
/// @param a pointer to first vector data
|
||||
/// @param b pointer to second vector data
|
||||
/// @param n length of vectors
|
||||
/// @param cellSize how many bits of the vectors will be added and treated as a single bit, can be 1 (standard Hamming distance), 2 or 4
|
||||
/// @param result pointer to result output
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_normHammingDiff8u(const uchar* a, const uchar* b, int n, int cellSize, int* result);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_mul8u16u(
|
||||
const uchar * src1_data,
|
||||
size_t src1_step,
|
||||
const uchar * src2_data,
|
||||
size_t src2_step,
|
||||
ushort * dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
double scale);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_sub8u32f(
|
||||
const uchar *src1_data,
|
||||
size_t src1_step,
|
||||
const uchar *src2_data,
|
||||
size_t src2_step,
|
||||
float *dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_transpose2d(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int src_width,
|
||||
int src_height,
|
||||
int element_size);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_meanStdDev(
|
||||
const uchar * src_data,
|
||||
size_t src_step,
|
||||
int width,
|
||||
int height,
|
||||
int src_type,
|
||||
double * mean_val,
|
||||
double * stddev_val,
|
||||
uchar * mask,
|
||||
size_t mask_step);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Flips a 2D array around vertical, horizontal, or both axes
|
||||
/// @param src_type source and destination image type
|
||||
/// @param src_data source image data
|
||||
/// @param src_step source image step
|
||||
/// @param src_width source and destination image width
|
||||
/// @param src_height source and destination image height
|
||||
/// @param dst_data destination image data
|
||||
/// @param dst_step destination image step
|
||||
/// @param flip_mode 0 flips around x-axis, 1 around y-axis, -1 both
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_flip(
|
||||
int src_type,
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
int src_width,
|
||||
int src_height,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int flip_mode);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Rotates a 2D array in multiples of 90 degrees.
|
||||
/// @param src_type source and destination image type
|
||||
/// @param src_data source image data
|
||||
/// @param src_step source image step
|
||||
/// @param src_width source image width
|
||||
/// @If angle has value [180] it is also destination image width
|
||||
/// If angle has values [90, 270] it is also destination image height
|
||||
/// @param src_height source and destination image height (destination image width for angles [90, 270])
|
||||
/// If angle has value [180] it is also destination image height
|
||||
/// If angle has values [90, 270] it is also destination image width
|
||||
/// @param dst_data destination image data
|
||||
/// @param dst_step destination image step
|
||||
/// @param angle clockwise angle for rotation in degrees from set [90, 180, 270]
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_rotate(
|
||||
int src_type,
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
int src_width,
|
||||
int src_height,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int angle);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief weighted sum of two arrays using formula: dst[i] = a * src1[i] + b * src2[i]
|
||||
/// @param src1_data first source image data
|
||||
/// @param src1_step first source image step
|
||||
/// @param src2_data second source image data
|
||||
/// @param src2_step second source image step
|
||||
/// @param dst_data destination image data
|
||||
/// @param dst_step destination image step
|
||||
/// @param width width of the images
|
||||
/// @param height height of the images
|
||||
/// @param scalars numbers a, b, and c
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_addWeighted8u(
|
||||
const uchar* src1_data,
|
||||
size_t src1_step,
|
||||
const uchar* src2_data,
|
||||
size_t src2_step,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
const double scalars[3]);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_mul8u(
|
||||
const uchar *src1_data,
|
||||
size_t src1_step,
|
||||
const uchar *src2_data,
|
||||
size_t src2_step,
|
||||
uchar *dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
double scale);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_mul16s(
|
||||
const short *src1_data,
|
||||
size_t src1_step,
|
||||
const short *src2_data,
|
||||
size_t src2_step,
|
||||
short *dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
double scale);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_mul32f(
|
||||
const float *src1_data,
|
||||
size_t src1_step,
|
||||
const float *src2_data,
|
||||
size_t src2_step,
|
||||
float *dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
double scale);
|
||||
|
||||
#endif
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_HAL_IMGPROC_HPP_INCLUDED
|
||||
#define OPENCV_FASTCV_HAL_IMGPROC_HPP_INCLUDED
|
||||
|
||||
#include <opencv2/core/base.hpp>
|
||||
|
||||
#undef cv_hal_medianBlur
|
||||
#define cv_hal_medianBlur fastcv_hal_medianBlur
|
||||
#undef cv_hal_sobel
|
||||
#define cv_hal_sobel fastcv_hal_sobel
|
||||
#undef cv_hal_boxFilter
|
||||
#define cv_hal_boxFilter fastcv_hal_boxFilter
|
||||
#undef cv_hal_adaptiveThreshold
|
||||
#define cv_hal_adaptiveThreshold fastcv_hal_adaptiveThreshold
|
||||
#undef cv_hal_gaussianBlurBinomial
|
||||
#define cv_hal_gaussianBlurBinomial fastcv_hal_gaussianBlurBinomial
|
||||
#undef cv_hal_warpPerspective
|
||||
#define cv_hal_warpPerspective fastcv_hal_warpPerspective
|
||||
#undef cv_hal_pyrdown
|
||||
#define cv_hal_pyrdown fastcv_hal_pyrdown
|
||||
#undef cv_hal_cvtBGRtoHSV
|
||||
#define cv_hal_cvtBGRtoHSV fastcv_hal_cvtBGRtoHSV
|
||||
#undef cv_hal_cvtBGRtoYUVApprox
|
||||
#define cv_hal_cvtBGRtoYUVApprox fastcv_hal_cvtBGRtoYUVApprox
|
||||
#undef cv_hal_canny
|
||||
#define cv_hal_canny fastcv_hal_canny
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Calculate medianBlur filter
|
||||
/// @param src_data Source image data
|
||||
/// @param src_step Source image step
|
||||
/// @param dst_data Destination image data
|
||||
/// @param dst_step Destination image step
|
||||
/// @param width Source image width
|
||||
/// @param height Source image height
|
||||
/// @param depth Depths of source and destination image
|
||||
/// @param cn Number of channels
|
||||
/// @param ksize Size of kernel
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_medianBlur(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
int depth,
|
||||
int cn,
|
||||
int ksize);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Computes Sobel derivatives
|
||||
///
|
||||
/// @param src_data Source image data
|
||||
/// @param src_step Source image step
|
||||
/// @param dst_data Destination image data
|
||||
/// @param dst_step Destination image step
|
||||
/// @param width Source image width
|
||||
/// @param height Source image height
|
||||
/// @param src_depth Depth of source image
|
||||
/// @param dst_depth Depths of destination image
|
||||
/// @param cn Number of channels
|
||||
/// @param margin_left Left margins for source image
|
||||
/// @param margin_top Top margins for source image
|
||||
/// @param margin_right Right margins for source image
|
||||
/// @param margin_bottom Bottom margins for source image
|
||||
/// @param dx orders of the derivative x
|
||||
/// @param dy orders of the derivative y
|
||||
/// @param ksize Size of kernel
|
||||
/// @param scale Scale factor for the computed derivative values
|
||||
/// @param delta Delta value that is added to the results prior to storing them in dst
|
||||
/// @param border_type Border type
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_sobel(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
int src_depth,
|
||||
int dst_depth,
|
||||
int cn,
|
||||
int margin_left,
|
||||
int margin_top,
|
||||
int margin_right,
|
||||
int margin_bottom,
|
||||
int dx,
|
||||
int dy,
|
||||
int ksize,
|
||||
double scale,
|
||||
double delta,
|
||||
int border_type);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int fastcv_hal_boxFilter(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
int src_depth,
|
||||
int dst_depth,
|
||||
int cn,
|
||||
int margin_left,
|
||||
int margin_top,
|
||||
int margin_right,
|
||||
int margin_bottom,
|
||||
size_t ksize_width,
|
||||
size_t ksize_height,
|
||||
int anchor_x,
|
||||
int anchor_y,
|
||||
bool normalize,
|
||||
int border_type);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_adaptiveThreshold(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
double maxValue,
|
||||
int adaptiveMethod,
|
||||
int thresholdType,
|
||||
int blockSize,
|
||||
double C);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Blurs an image using a Gaussian filter.
|
||||
/// @param src_data Source image data
|
||||
/// @param src_step Source image step
|
||||
/// @param dst_data Destination image data
|
||||
/// @param dst_step Destination image step
|
||||
/// @param width Source image width
|
||||
/// @param height Source image height
|
||||
/// @param depth Depth of source and destination image
|
||||
/// @param cn Number of channels
|
||||
/// @param margin_left Left margins for source image
|
||||
/// @param margin_top Top margins for source image
|
||||
/// @param margin_right Right margins for source image
|
||||
/// @param margin_bottom Bottom margins for source image
|
||||
/// @param ksize Kernel size
|
||||
/// @param border_type Border type
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_gaussianBlurBinomial(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
int depth,
|
||||
int cn,
|
||||
size_t margin_left,
|
||||
size_t margin_top,
|
||||
size_t margin_right,
|
||||
size_t margin_bottom,
|
||||
size_t ksize,
|
||||
int border_type);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Applies a perspective transformation to an image.
|
||||
///
|
||||
/// @param src_type Source and destination image type
|
||||
/// @param src_data Source image data
|
||||
/// @param src_step Source image step
|
||||
/// @param src_width Source image width
|
||||
/// @param src_height Source image height
|
||||
/// @param dst_data Destination image data
|
||||
/// @param dst_step Destination image step
|
||||
/// @param dst_width Destination image width
|
||||
/// @param dst_height Destination image height
|
||||
/// @param M 3x3 matrix with transform coefficients
|
||||
/// @param interpolation Interpolation mode (CV_HAL_INTER_NEAREST, ...)
|
||||
/// @param border_type Border processing mode (CV_HAL_BORDER_REFLECT, ...)
|
||||
/// @param border_value Values to use for CV_HAL_BORDER_CONSTANT mode
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_warpPerspective(
|
||||
int src_type,
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
int src_width,
|
||||
int src_height,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
const double M[9],
|
||||
int interpolation,
|
||||
int border_type,
|
||||
const double border_value[4]);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_pyrdown(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
int src_width,
|
||||
int src_height,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
int depth,
|
||||
int cn,
|
||||
int border_type);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_cvtBGRtoHSV(
|
||||
const uchar * src_data,
|
||||
size_t src_step,
|
||||
uchar * dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
int depth,
|
||||
int scn,
|
||||
bool swapBlue,
|
||||
bool isFullRange,
|
||||
bool isHSV);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_cvtBGRtoYUVApprox(
|
||||
const uchar * src_data,
|
||||
size_t src_step,
|
||||
uchar * dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
int depth,
|
||||
int scn,
|
||||
bool swapBlue,
|
||||
bool isCbCr);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Canny edge detector
|
||||
/// @param src_data Source image data
|
||||
/// @param src_step Source image step
|
||||
/// @param dst_data Destination image data
|
||||
/// @param dst_step Destination image step
|
||||
/// @param width Source image width
|
||||
/// @param height Source image height
|
||||
/// @param cn Number of channels
|
||||
/// @param lowThreshold low hresholds value
|
||||
/// @param highThreshold high thresholds value
|
||||
/// @param ksize Kernel size for Sobel operator.
|
||||
/// @param L2gradient Flag, indicating use of L2 or L1 norma.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int fastcv_hal_canny(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
int cn,
|
||||
double lowThreshold,
|
||||
double highThreshold,
|
||||
int ksize,
|
||||
bool L2gradient);
|
||||
|
||||
#endif
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_HAL_UTILS_HPP_INCLUDED
|
||||
#define OPENCV_FASTCV_HAL_UTILS_HPP_INCLUDED
|
||||
|
||||
#include "fastcv.h"
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
|
||||
#define INITIALIZATION_CHECK \
|
||||
{ \
|
||||
if (!FastCvContext::getContext().isInitialized) \
|
||||
{ \
|
||||
return CV_HAL_ERROR_UNKNOWN; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CV_HAL_RETURN(status, func) \
|
||||
{ \
|
||||
if( status == FASTCV_SUCCESS ) \
|
||||
{ \
|
||||
CV_LOG_DEBUG(NULL, "FastCV HAL for "<<#func<<" run successfully!"); \
|
||||
return CV_HAL_ERROR_OK; \
|
||||
} \
|
||||
else if(status == FASTCV_EBADPARAM || status == FASTCV_EUNALIGNPARAM || \
|
||||
status == FASTCV_EUNSUPPORTED || status == FASTCV_EHWQDSP || \
|
||||
status == FASTCV_EHWGPU) \
|
||||
{ \
|
||||
CV_LOG_DEBUG(NULL, "FastCV status:"<<getFastCVErrorString(status) \
|
||||
<<", Switching to default OpenCV solution!"); \
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
CV_LOG_ERROR(NULL,"FastCV error:"<<getFastCVErrorString(status)); \
|
||||
return CV_HAL_ERROR_UNKNOWN; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CV_HAL_RETURN_NOT_IMPLEMENTED(reason) \
|
||||
{ \
|
||||
CV_LOG_DEBUG(NULL,"Switching to default OpenCV\nInfo: "<<reason); \
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED; \
|
||||
}
|
||||
|
||||
#define FCV_KernelSize_SHIFT 3
|
||||
#define FCV_MAKETYPE(ksize,depth) ((ksize<<FCV_KernelSize_SHIFT) + depth)
|
||||
#define FCV_CMP_EQ(val1,val2) (fabs(val1 - val2) < FLT_EPSILON)
|
||||
|
||||
const char* getFastCVErrorString(int status);
|
||||
const char* borderToString(int border);
|
||||
const char* interpolationToString(int interpolation);
|
||||
|
||||
struct FastCvContext
|
||||
{
|
||||
public:
|
||||
// initialize at first call
|
||||
// Defines a static local variable context. Variable is created only once.
|
||||
static FastCvContext& getContext()
|
||||
{
|
||||
static FastCvContext context;
|
||||
return context;
|
||||
}
|
||||
|
||||
FastCvContext()
|
||||
{
|
||||
if (fcvSetOperationMode(FASTCV_OP_CPU_PERFORMANCE) != 0)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Failed to switch FastCV operation mode");
|
||||
isInitialized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_INFO(NULL, "FastCV Operation Mode Switched");
|
||||
isInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isInitialized;
|
||||
};
|
||||
|
||||
#endif
|
||||
+574
@@ -0,0 +1,574 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "fastcv_hal_core.hpp"
|
||||
#include "fastcv_hal_utils.hpp"
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/core/base.hpp>
|
||||
|
||||
|
||||
class ParallelTableLookup : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
|
||||
ParallelTableLookup(const uchar* src_data_, int width_, size_t src_step_, const uchar* lut_data_, uchar* dst_data_, size_t dst_step_) :
|
||||
cv::ParallelLoopBody(), src_data(src_data_), width(width_), src_step(src_step_), lut_data(lut_data_), dst_data(dst_data_), dst_step(dst_step_)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(const cv::Range& range) const CV_OVERRIDE
|
||||
{
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
for (int y = range.start; y < range.end; y++) {
|
||||
status = fcvTableLookupu8((uint8_t*)src_data + y * src_step, width, 1, src_step, (uint8_t*)lut_data, (uint8_t*)dst_data + y * dst_step, dst_step);
|
||||
if(status != FASTCV_SUCCESS)
|
||||
CV_LOG_ERROR(NULL,"FastCV error:"<<getFastCVErrorString(status));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const uchar* src_data;
|
||||
int width;
|
||||
size_t src_step;
|
||||
const uchar* lut_data;
|
||||
uchar* dst_data;
|
||||
size_t dst_step;
|
||||
};
|
||||
|
||||
int fastcv_hal_lut(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
size_t src_type,
|
||||
const uchar* lut_data,
|
||||
size_t lut_channel_size,
|
||||
size_t lut_channels,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if((width*height)<=(320*240))
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("Switching to default OpenCV solution!");
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
fcvStatus status;
|
||||
if (src_type == CV_8UC1 && lut_channels == 1 && lut_channel_size == 1)
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, height),
|
||||
ParallelTableLookup(src_data, width, src_step, lut_data, dst_data, dst_step));
|
||||
status = FASTCV_SUCCESS;
|
||||
CV_HAL_RETURN(status, hal_lut);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("Multi-channel input is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
int fastcv_hal_normHammingDiff8u(
|
||||
const uchar* a,
|
||||
const uchar* b,
|
||||
int n,
|
||||
int cellSize,
|
||||
int* result)
|
||||
{
|
||||
fcvStatus status;
|
||||
|
||||
if (cellSize != 1)
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("NORM_HAMMING2 cellSize:%d is not supported", cellSize));
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
uint32_t dist = 0;
|
||||
|
||||
dist = fcvHammingDistanceu8((uint8_t*)a, (uint8_t*)b, n);
|
||||
|
||||
*result = dist;
|
||||
status = FASTCV_SUCCESS;
|
||||
CV_HAL_RETURN(status, hal_normHammingDiff8u);
|
||||
}
|
||||
|
||||
int fastcv_hal_mul8u16u(
|
||||
const uchar* src1_data,
|
||||
size_t src1_step,
|
||||
const uchar* src2_data,
|
||||
size_t src2_step,
|
||||
ushort* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
double scale)
|
||||
{
|
||||
if(scale != 1.0)
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("Scale factor not supported");
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
|
||||
if (src1_step < (size_t)width && src2_step < (size_t)width)
|
||||
{
|
||||
src1_step = width*sizeof(uchar);
|
||||
src2_step = width*sizeof(uchar);
|
||||
dst_step = width*sizeof(ushort);
|
||||
}
|
||||
|
||||
status = fcvElementMultiplyu8u16_v2(src1_data, width, height, src1_step,
|
||||
src2_data, src2_step, dst_data, dst_step);
|
||||
|
||||
CV_HAL_RETURN(status,hal_multiply);
|
||||
}
|
||||
|
||||
int fastcv_hal_sub8u32f(
|
||||
const uchar* src1_data,
|
||||
size_t src1_step,
|
||||
const uchar* src2_data,
|
||||
size_t src2_step,
|
||||
float* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
|
||||
if (src1_step < (size_t)width && src2_step < (size_t)width)
|
||||
{
|
||||
src1_step = width*sizeof(uchar);
|
||||
src2_step = width*sizeof(uchar);
|
||||
dst_step = width*sizeof(float);
|
||||
}
|
||||
|
||||
status = fcvImageDiffu8f32_v2(src1_data, src2_data, width, height, src1_step,
|
||||
src2_step, dst_data, dst_step);
|
||||
|
||||
CV_HAL_RETURN(status,hal_subtract);
|
||||
|
||||
}
|
||||
|
||||
int fastcv_hal_transpose2d(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int src_width,
|
||||
int src_height,
|
||||
int element_size)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
if (src_data == dst_data)
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("In-place not supported");
|
||||
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
|
||||
switch (element_size)
|
||||
{
|
||||
case 1:
|
||||
status = fcvTransposeu8_v2(src_data, src_width, src_height, src_step,
|
||||
dst_data, dst_step);
|
||||
break;
|
||||
case 2:
|
||||
status = fcvTransposeu16_v2((const uint16_t*)src_data, src_width, src_height,
|
||||
src_step, (uint16_t*)dst_data, dst_step);
|
||||
break;
|
||||
case 4:
|
||||
status = fcvTransposef32_v2((const float32_t*)src_data, src_width, src_height,
|
||||
src_step, (float32_t*)dst_data, dst_step);
|
||||
break;
|
||||
default:
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("srcType not supported");
|
||||
}
|
||||
|
||||
CV_HAL_RETURN(status,hal_transpose);
|
||||
}
|
||||
|
||||
int fastcv_hal_meanStdDev(
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
int width,
|
||||
int height,
|
||||
int src_type,
|
||||
double* mean_val,
|
||||
double* stddev_val,
|
||||
uchar* mask,
|
||||
size_t mask_step)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_UNUSED(mask_step);
|
||||
|
||||
if(src_type != CV_8UC1)
|
||||
{
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("src type not supported");
|
||||
}
|
||||
else if(mask != nullptr)
|
||||
{
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("mask not supported");
|
||||
}
|
||||
else if(mean_val == nullptr && stddev_val == nullptr)
|
||||
{
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("null ptr for mean and stddev");
|
||||
}
|
||||
|
||||
float32_t mean, variance;
|
||||
|
||||
fcvStatus status = fcvImageIntensityStats_v2(src_data, src_step, 0, 0, width, height,
|
||||
&mean, &variance, FASTCV_BIASED_VARIANCE_ESTIMATOR);
|
||||
|
||||
if(mean_val != nullptr)
|
||||
*mean_val = mean;
|
||||
if(stddev_val != nullptr)
|
||||
*stddev_val = std::sqrt(variance);
|
||||
|
||||
CV_HAL_RETURN(status,hal_meanStdDev);
|
||||
}
|
||||
|
||||
int fastcv_hal_flip(
|
||||
int src_type,
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
int src_width,
|
||||
int src_height,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int flip_mode)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
if(src_type!=CV_8UC1 && src_type!=CV_16UC1 && src_type!=CV_8UC3)
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("Data type is not supported, Switching to default OpenCV solution!");
|
||||
|
||||
if((src_width*src_height)<=(640*480))
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("Switching to default OpenCV solution!");
|
||||
|
||||
fcvStatus status = FASTCV_SUCCESS;;
|
||||
fcvFlipDir dir;
|
||||
|
||||
switch (flip_mode)
|
||||
{
|
||||
//Flip around X-Axis: Vertical Flip or FLIP_ROWS
|
||||
case 0:
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("Switching to default OpenCV solution due to low perf!");
|
||||
dir = FASTCV_FLIP_VERT;
|
||||
break;
|
||||
|
||||
//Flip around Y-Axis: Horizontal Flip or FLIP_COLS
|
||||
case 1:
|
||||
dir = FASTCV_FLIP_HORIZ;
|
||||
break;
|
||||
|
||||
//Flip around both X and Y-Axis or FLIP_BOTH
|
||||
case -1:
|
||||
dir = FASTCV_FLIP_BOTH;
|
||||
break;
|
||||
default:
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("Invalid flip_mode, Switching to default OpenCV solution!");
|
||||
}
|
||||
|
||||
if(src_type==CV_8UC1)
|
||||
fcvFlipu8(src_data, src_width, src_height, src_step, dst_data, dst_step, dir);
|
||||
else if(src_type==CV_16UC1)
|
||||
fcvFlipu16((uint16_t*)src_data, src_width, src_height, src_step, (uint16_t*)dst_data, dst_step, dir);
|
||||
else if(src_type==CV_8UC3)
|
||||
status = fcvFlipRGB888u8((uint8_t*)src_data, src_width, src_height, src_step, (uint8_t*)dst_data, dst_step, dir);
|
||||
else
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("Data type:%d is not supported, Switching to default OpenCV solution!", src_type));
|
||||
|
||||
CV_HAL_RETURN(status, hal_flip);
|
||||
}
|
||||
|
||||
int fastcv_hal_rotate(
|
||||
int src_type,
|
||||
const uchar* src_data,
|
||||
size_t src_step,
|
||||
int src_width,
|
||||
int src_height,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int angle)
|
||||
{
|
||||
if((src_width*src_height)<(120*80))
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("Switching to default OpenCV solution for lower resolution!");
|
||||
|
||||
fcvStatus status;
|
||||
fcvRotateDegree degree;
|
||||
|
||||
if (src_type != CV_8UC1 && src_type != CV_8UC2)
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("src_type:%d is not supported", src_type));
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
switch (angle)
|
||||
{
|
||||
case 90:
|
||||
degree = FASTCV_ROTATE_90;
|
||||
break;
|
||||
case 180:
|
||||
degree = FASTCV_ROTATE_180;
|
||||
break;
|
||||
case 270:
|
||||
degree = FASTCV_ROTATE_270;
|
||||
break;
|
||||
default:
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("Rotation angle:%d is not supported", angle));
|
||||
}
|
||||
|
||||
switch(src_type)
|
||||
{
|
||||
case CV_8UC1:
|
||||
status = fcvRotateImageu8(src_data, src_width, src_height, src_step, dst_data, dst_step, degree);
|
||||
break;
|
||||
case CV_8UC2:
|
||||
status = fcvRotateImageInterleavedu8((uint8_t*)src_data, src_width, src_height, src_step, (uint8_t*)dst_data,
|
||||
dst_step, degree);
|
||||
break;
|
||||
default:
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("src_type:%d is not supported", src_type));
|
||||
}
|
||||
CV_HAL_RETURN(status, hal_rotate);
|
||||
}
|
||||
|
||||
int fastcv_hal_addWeighted8u(
|
||||
const uchar* src1_data,
|
||||
size_t src1_step,
|
||||
const uchar* src2_data,
|
||||
size_t src2_step,
|
||||
uchar* dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
const double scalars[3])
|
||||
{
|
||||
if( (scalars[0] < -128.0f) || (scalars[0] >= 128.0f) ||
|
||||
(scalars[1] < -128.0f) || (scalars[1] >= 128.0f) ||
|
||||
(scalars[2] < -(1<<23))|| (scalars[2] >= 1<<23))
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED(
|
||||
cv::format("Alpha:%f,Beta:%f,Gamma:%f is not supported because it's too large or too small\n",
|
||||
scalars[0],scalars[1],scalars[2]));
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
|
||||
if (height == 1)
|
||||
{
|
||||
src1_step = width*sizeof(uchar);
|
||||
src2_step = width*sizeof(uchar);
|
||||
dst_step = width*sizeof(uchar);
|
||||
|
||||
cv::parallel_for_(cv::Range(0, width), [&](const cv::Range &range){
|
||||
int rangeWidth = range.end - range.start;
|
||||
const uint8_t *src1 = src1_data + range.start;
|
||||
const uint8_t *src2 = src2_data + range.start;
|
||||
uint8_t *dst = dst_data + range.start;
|
||||
fcvAddWeightedu8_v2(src1, rangeWidth, height, src1_step, src2, src2_step,
|
||||
scalars[0], scalars[1], scalars[2], dst, dst_step);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, height), [&](const cv::Range &range){
|
||||
int rangeHeight = range.end - range.start;
|
||||
const uint8_t *src1 = src1_data + range.start * src1_step;
|
||||
const uint8_t *src2 = src2_data + range.start * src2_step;
|
||||
uint8_t *dst = dst_data + range.start * dst_step;
|
||||
fcvAddWeightedu8_v2(src1, width, rangeHeight, src1_step, src2, src2_step,
|
||||
scalars[0], scalars[1], scalars[2], dst, dst_step);
|
||||
});
|
||||
}
|
||||
|
||||
CV_HAL_RETURN(status, hal_addWeighted8u_v2);
|
||||
}
|
||||
|
||||
int fastcv_hal_mul8u(
|
||||
const uchar *src1_data,
|
||||
size_t src1_step,
|
||||
const uchar *src2_data,
|
||||
size_t src2_step,
|
||||
uchar *dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
double scale)
|
||||
{
|
||||
int8_t sF;
|
||||
|
||||
if(FCV_CMP_EQ(scale,1.0)) { sF = 0; }
|
||||
else if(scale > 1.0)
|
||||
{
|
||||
if(FCV_CMP_EQ(scale,2.0)) { sF = -1; }
|
||||
else if(FCV_CMP_EQ(scale,4.0)) { sF = -2; }
|
||||
else if(FCV_CMP_EQ(scale,8.0)) { sF = -3; }
|
||||
else if(FCV_CMP_EQ(scale,16.0)) { sF = -4; }
|
||||
else if(FCV_CMP_EQ(scale,32.0)) { sF = -5; }
|
||||
else if(FCV_CMP_EQ(scale,64.0)) { sF = -6; }
|
||||
else if(FCV_CMP_EQ(scale,128.0)) { sF = -7; }
|
||||
else if(FCV_CMP_EQ(scale,256.0)) { sF = -8; }
|
||||
else CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported");
|
||||
}
|
||||
else if(scale > 0 && scale < 1.0)
|
||||
{
|
||||
if(FCV_CMP_EQ(scale,1/2.0)) { sF = 1; }
|
||||
else if(FCV_CMP_EQ(scale,1/4.0)) { sF = 2; }
|
||||
else if(FCV_CMP_EQ(scale,1/8.0)) { sF = 3; }
|
||||
else if(FCV_CMP_EQ(scale,1/16.0)) { sF = 4; }
|
||||
else if(FCV_CMP_EQ(scale,1/32.0)) { sF = 5; }
|
||||
else if(FCV_CMP_EQ(scale,1/64.0)) { sF = 6; }
|
||||
else if(FCV_CMP_EQ(scale,1/128.0)) { sF = 7; }
|
||||
else if(FCV_CMP_EQ(scale,1/256.0)) { sF = 8; }
|
||||
else CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported");
|
||||
}
|
||||
else
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported");
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
int nStripes = cv::getNumThreads();
|
||||
|
||||
if(height == 1)
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, width), [&](const cv::Range &range){
|
||||
int rangeWidth = range.end - range.start;
|
||||
const uchar* yS1 = src1_data + static_cast<size_t>(range.start);
|
||||
const uchar* yS2 = src2_data + static_cast<size_t>(range.start);
|
||||
uchar* yD = dst_data + static_cast<size_t>(range.start);
|
||||
fcvElementMultiplyu8(yS1, rangeWidth, 1, 0, yS2, 0, sF,
|
||||
FASTCV_CONVERT_POLICY_SATURATE, yD, 0);
|
||||
}, nStripes);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, height), [&](const cv::Range &range){
|
||||
int rangeHeight = range.end - range.start;
|
||||
const uchar* yS1 = src1_data + static_cast<size_t>(range.start)*src1_step;
|
||||
const uchar* yS2 = src2_data + static_cast<size_t>(range.start)*src2_step;
|
||||
uchar* yD = dst_data + static_cast<size_t>(range.start)*dst_step;
|
||||
fcvElementMultiplyu8(yS1, width, rangeHeight, src1_step, yS2, src2_step,
|
||||
sF, FASTCV_CONVERT_POLICY_SATURATE, yD, dst_step);
|
||||
}, nStripes);
|
||||
}
|
||||
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
CV_HAL_RETURN(status, hal_mul8u);
|
||||
}
|
||||
|
||||
int fastcv_hal_mul16s(
|
||||
const short *src1_data,
|
||||
size_t src1_step,
|
||||
const short *src2_data,
|
||||
size_t src2_step,
|
||||
short *dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
double scale)
|
||||
{
|
||||
int8_t sF;
|
||||
|
||||
if(FCV_CMP_EQ(scale,1.0)) { sF = 0; }
|
||||
else if(scale > 1.0)
|
||||
{
|
||||
if(FCV_CMP_EQ(scale,2.0)) { sF = -1; }
|
||||
else if(FCV_CMP_EQ(scale,4.0)) { sF = -2; }
|
||||
else if(FCV_CMP_EQ(scale,8.0)) { sF = -3; }
|
||||
else if(FCV_CMP_EQ(scale,16.0)) { sF = -4; }
|
||||
else if(FCV_CMP_EQ(scale,32.0)) { sF = -5; }
|
||||
else if(FCV_CMP_EQ(scale,64.0)) { sF = -6; }
|
||||
else if(FCV_CMP_EQ(scale,128.0)) { sF = -7; }
|
||||
else if(FCV_CMP_EQ(scale,256.0)) { sF = -8; }
|
||||
else CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported");
|
||||
}
|
||||
else if(scale > 0 && scale < 1.0)
|
||||
{
|
||||
if(FCV_CMP_EQ(scale,1/2.0)) { sF = 1; }
|
||||
else if(FCV_CMP_EQ(scale,1/4.0)) { sF = 2; }
|
||||
else if(FCV_CMP_EQ(scale,1/8.0)) { sF = 3; }
|
||||
else if(FCV_CMP_EQ(scale,1/16.0)) { sF = 4; }
|
||||
else if(FCV_CMP_EQ(scale,1/32.0)) { sF = 5; }
|
||||
else if(FCV_CMP_EQ(scale,1/64.0)) { sF = 6; }
|
||||
else if(FCV_CMP_EQ(scale,1/128.0)) { sF = 7; }
|
||||
else if(FCV_CMP_EQ(scale,1/256.0)) { sF = 8; }
|
||||
else CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported");
|
||||
}
|
||||
else
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported");
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
int nStripes = cv::getNumThreads();
|
||||
|
||||
if(height == 1)
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, width), [&](const cv::Range &range){
|
||||
int rangeWidth = range.end - range.start;
|
||||
const short* yS1 = src1_data + static_cast<size_t>(range.start);
|
||||
const short* yS2 = src2_data + static_cast<size_t>(range.start);
|
||||
short* yD = dst_data + static_cast<size_t>(range.start);
|
||||
fcvElementMultiplys16(yS1, rangeWidth, 1, 0, yS2, 0, sF,
|
||||
FASTCV_CONVERT_POLICY_SATURATE, yD, 0);
|
||||
}, nStripes);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, height), [&](const cv::Range &range){
|
||||
int rangeHeight = range.end - range.start;
|
||||
const short* yS1 = src1_data + static_cast<size_t>(range.start) * (src1_step/sizeof(short));
|
||||
const short* yS2 = src2_data + static_cast<size_t>(range.start) * (src2_step/sizeof(short));
|
||||
short* yD = dst_data + static_cast<size_t>(range.start) * (dst_step/sizeof(short));
|
||||
fcvElementMultiplys16(yS1, width, rangeHeight, src1_step, yS2, src2_step,
|
||||
sF, FASTCV_CONVERT_POLICY_SATURATE, yD, dst_step);
|
||||
}, nStripes);
|
||||
}
|
||||
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
CV_HAL_RETURN(status, hal_mul16s);
|
||||
}
|
||||
|
||||
int fastcv_hal_mul32f(
|
||||
const float *src1_data,
|
||||
size_t src1_step,
|
||||
const float *src2_data,
|
||||
size_t src2_step,
|
||||
float *dst_data,
|
||||
size_t dst_step,
|
||||
int width,
|
||||
int height,
|
||||
double scale)
|
||||
{
|
||||
if(!FCV_CMP_EQ(scale,1.0))
|
||||
CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported");
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
int nStripes = cv::getNumThreads();
|
||||
|
||||
if(height == 1)
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, width), [&](const cv::Range &range){
|
||||
int rangeWidth = range.end - range.start;
|
||||
const float* yS1 = src1_data + static_cast<size_t>(range.start);
|
||||
const float* yS2 = src2_data + static_cast<size_t>(range.start);
|
||||
float* yD = dst_data + static_cast<size_t>(range.start);
|
||||
fcvElementMultiplyf32(yS1, rangeWidth, 1, 0, yS2, 0, yD, 0);
|
||||
}, nStripes);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, height), [&](const cv::Range &range){
|
||||
int rangeHeight = range.end - range.start;
|
||||
const float* yS1 = src1_data + static_cast<size_t>(range.start) * (src1_step/sizeof(float));
|
||||
const float* yS2 = src2_data + static_cast<size_t>(range.start) * (src2_step/sizeof(float));
|
||||
float* yD = dst_data + static_cast<size_t>(range.start) * (dst_step/sizeof(float));
|
||||
fcvElementMultiplyf32(yS1, width, rangeHeight, src1_step,
|
||||
yS2, src2_step, yD, dst_step);
|
||||
}, nStripes);
|
||||
}
|
||||
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
CV_HAL_RETURN(status, hal_mul32f);
|
||||
}
|
||||
+1050
File diff suppressed because it is too large
Load Diff
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "fastcv_hal_utils.hpp"
|
||||
|
||||
const char* getFastCVErrorString(int status)
|
||||
{
|
||||
switch(status)
|
||||
{
|
||||
case FASTCV_SUCCESS: return "Successful";
|
||||
case FASTCV_EFAIL: return "General failure";
|
||||
case FASTCV_EUNALIGNPARAM: return "Unaligned pointer parameter";
|
||||
case FASTCV_EBADPARAM: return "Bad parameters";
|
||||
case FASTCV_EINVALSTATE: return "Called at invalid state";
|
||||
case FASTCV_ENORES: return "Insufficient resources, memory, thread, etc";
|
||||
case FASTCV_EUNSUPPORTED: return "Unsupported feature";
|
||||
case FASTCV_EHWQDSP: return "Hardware QDSP failed to respond";
|
||||
case FASTCV_EHWGPU: return "Hardware GPU failed to respond";
|
||||
default: return "Unknown FastCV Error";
|
||||
}
|
||||
}
|
||||
|
||||
const char* borderToString(int border)
|
||||
{
|
||||
switch (border)
|
||||
{
|
||||
case 0: return "BORDER_CONSTANT";
|
||||
case 1: return "BORDER_REPLICATE";
|
||||
case 2: return "BORDER_REFLECT";
|
||||
case 3: return "BORDER_WRAP";
|
||||
case 4: return "BORDER_REFLECT_101";
|
||||
case 5: return "BORDER_TRANSPARENT";
|
||||
default: return "Unknown border type";
|
||||
}
|
||||
}
|
||||
|
||||
const char* interpolationToString(int interpolation)
|
||||
{
|
||||
switch (interpolation)
|
||||
{
|
||||
case 0: return "INTER_NEAREST";
|
||||
case 1: return "INTER_LINEAR";
|
||||
case 2: return "INTER_CUBIC";
|
||||
case 3: return "INTER_AREA";
|
||||
case 4: return "INTER_LANCZOS4";
|
||||
case 5: return "INTER_LINEAR_EXACT";
|
||||
case 6: return "INTER_NEAREST_EXACT";
|
||||
case 7: return "INTER_MAX";
|
||||
case 8: return "WARP_FILL_OUTLIERS";
|
||||
case 16: return "WARP_INVERSE_MAP";
|
||||
case 32: return "WARP_RELATIVE_MAP";
|
||||
default: return "Unknown interpolation type";
|
||||
}
|
||||
}
|
||||
Vendored
+5
-5
@@ -1,8 +1,8 @@
|
||||
# Binaries branch name: ffmpeg/4.x_20240522
|
||||
# Binaries were created for OpenCV: 8393885a39dac1e650bf5d0aaff84c04ad8bcdd3
|
||||
ocv_update(FFMPEG_BINARIES_COMMIT "394dca6ceb3085c979415e6385996b6570e94153")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN32 "bdfbd1efb295f3e54c07d2cb7a843bf9")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN64 "bfef029900f788480a363d6dc05c4f0e")
|
||||
# Binaries branch name: ffmpeg/4.x_20241226
|
||||
# Binaries were created for OpenCV: 09892c9d1706f40342bda0bc404580f63492d9f8
|
||||
ocv_update(FFMPEG_BINARIES_COMMIT "d63d7c154c57242bf2283be61166be2bd30ec47e")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN32 "642b94d032a8292b07550126934173f6")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN64 "a8c3560c8f20e1ae465bef81580fa92c")
|
||||
ocv_update(FFMPEG_FILE_HASH_CMAKE "8862c87496e2e8c375965e1277dee1c7")
|
||||
|
||||
function(download_win_ffmpeg script_var)
|
||||
|
||||
Vendored
+1
@@ -21,6 +21,7 @@
|
||||
|
||||
#if defined(__riscv_v) && __riscv_v == 1000000
|
||||
#include "hal_rvv_1p0/merge.hpp" // core
|
||||
#include "hal_rvv_1p0/mean.hpp" // core
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
// 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.
|
||||
#ifndef OPENCV_HAL_RVV_MEANSTDDEV_HPP_INCLUDED
|
||||
#define OPENCV_HAL_RVV_MEANSTDDEV_HPP_INCLUDED
|
||||
|
||||
#include <riscv_vector.h>
|
||||
|
||||
namespace cv { namespace cv_hal_rvv {
|
||||
|
||||
#undef cv_hal_meanStdDev
|
||||
#define cv_hal_meanStdDev cv::cv_hal_rvv::meanStdDev
|
||||
|
||||
inline int meanStdDev_8UC1(const uchar* src_data, size_t src_step, int width, int height,
|
||||
double* mean_val, double* stddev_val, uchar* mask, size_t mask_step);
|
||||
inline int meanStdDev_8UC4(const uchar* src_data, size_t src_step, int width, int height,
|
||||
double* mean_val, double* stddev_val, uchar* mask, size_t mask_step);
|
||||
inline int meanStdDev_32FC1(const uchar* src_data, size_t src_step, int width, int height,
|
||||
double* mean_val, double* stddev_val, uchar* mask, size_t mask_step);
|
||||
|
||||
inline int meanStdDev(const uchar* src_data, size_t src_step, int width, int height,
|
||||
int src_type, double* mean_val, double* stddev_val, uchar* mask, size_t mask_step) {
|
||||
switch (src_type)
|
||||
{
|
||||
case CV_8UC1:
|
||||
return meanStdDev_8UC1(src_data, src_step, width, height, mean_val, stddev_val, mask, mask_step);
|
||||
case CV_8UC4:
|
||||
return meanStdDev_8UC4(src_data, src_step, width, height, mean_val, stddev_val, mask, mask_step);
|
||||
case CV_32FC1:
|
||||
return meanStdDev_32FC1(src_data, src_step, width, height, mean_val, stddev_val, mask, mask_step);
|
||||
default:
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
||||
inline int meanStdDev_8UC1(const uchar* src_data, size_t src_step, int width, int height,
|
||||
double* mean_val, double* stddev_val, uchar* mask, size_t mask_step) {
|
||||
int nz = 0;
|
||||
int vlmax = __riscv_vsetvlmax_e64m8();
|
||||
vuint64m8_t vec_sum = __riscv_vmv_v_x_u64m8(0, vlmax);
|
||||
vuint64m8_t vec_sqsum = __riscv_vmv_v_x_u64m8(0, vlmax);
|
||||
if (mask) {
|
||||
for (int i = 0; i < height; ++i) {
|
||||
const uchar* src_row = src_data + i * src_step;
|
||||
const uchar* mask_row = mask + i * mask_step;
|
||||
int j = 0, vl;
|
||||
for ( ; j < width; j += vl) {
|
||||
vl = __riscv_vsetvl_e8m1(width - j);
|
||||
auto vec_pixel_u8 = __riscv_vle8_v_u8m1(src_row + j, vl);
|
||||
auto vmask_u8 = __riscv_vle8_v_u8m1(mask_row+j, vl);
|
||||
auto vec_pixel = __riscv_vzext_vf4(vec_pixel_u8, vl);
|
||||
auto vmask = __riscv_vmseq_vx_u8m1_b8(vmask_u8, 1, vl);
|
||||
vec_sum = __riscv_vwaddu_wv_u64m8_tumu(vmask, vec_sum, vec_sum, vec_pixel, vl);
|
||||
vec_sqsum = __riscv_vwmaccu_vv_u64m8_tumu(vmask, vec_sqsum, vec_pixel, vec_pixel, vl);
|
||||
nz += __riscv_vcpop_m_b8(vmask, vl);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < height; i++) {
|
||||
const uchar* src_row = src_data + i * src_step;
|
||||
int j = 0, vl;
|
||||
for ( ; j < width; j += vl) {
|
||||
vl = __riscv_vsetvl_e8m1(width - j);
|
||||
auto vec_pixel_u8 = __riscv_vle8_v_u8m1(src_row + j, vl);
|
||||
auto vec_pixel = __riscv_vzext_vf4(vec_pixel_u8, vl);
|
||||
vec_sum = __riscv_vwaddu_wv_u64m8_tu(vec_sum, vec_sum, vec_pixel, vl);
|
||||
vec_sqsum = __riscv_vwmaccu_vv_u64m8_tu(vec_sqsum, vec_pixel, vec_pixel, vl);
|
||||
}
|
||||
}
|
||||
nz = height * width;
|
||||
}
|
||||
if (nz == 0) {
|
||||
if (mean_val) *mean_val = 0.0;
|
||||
if (stddev_val) *stddev_val = 0.0;
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
auto zero = __riscv_vmv_s_x_u64m1(0, vlmax);
|
||||
auto vec_red = __riscv_vmv_v_x_u64m1(0, vlmax);
|
||||
auto vec_reddev = __riscv_vmv_v_x_u64m1(0, vlmax);
|
||||
vec_red = __riscv_vredsum(vec_sum, zero, vlmax);
|
||||
vec_reddev = __riscv_vredsum(vec_sqsum, zero, vlmax);
|
||||
double sum = __riscv_vmv_x(vec_red);
|
||||
double mean = sum / nz;
|
||||
if (mean_val) {
|
||||
*mean_val = mean;
|
||||
}
|
||||
if (stddev_val) {
|
||||
double sqsum = __riscv_vmv_x(vec_reddev);
|
||||
double variance = std::max((sqsum / nz) - (mean * mean), 0.0);
|
||||
double stddev = std::sqrt(variance);
|
||||
*stddev_val = stddev;
|
||||
}
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
inline int meanStdDev_8UC4(const uchar* src_data, size_t src_step, int width, int height,
|
||||
double* mean_val, double* stddev_val, uchar* mask, size_t mask_step) {
|
||||
int nz = 0;
|
||||
int vlmax = __riscv_vsetvlmax_e64m8();
|
||||
vuint64m8_t vec_sum = __riscv_vmv_v_x_u64m8(0, vlmax);
|
||||
vuint64m8_t vec_sqsum = __riscv_vmv_v_x_u64m8(0, vlmax);
|
||||
if (mask) {
|
||||
for (int i = 0; i < height; ++i) {
|
||||
const uchar* src_row = src_data + i * src_step;
|
||||
const uchar* mask_row = mask + i * mask_step;
|
||||
int j = 0, jm = 0, vl, vlm;
|
||||
for ( ; j < width*4; j += vl, jm += vlm) {
|
||||
vl = __riscv_vsetvl_e8m1(width*4 - j);
|
||||
vlm = __riscv_vsetvl_e8mf4(width - jm);
|
||||
auto vec_pixel_u8 = __riscv_vle8_v_u8m1(src_row + j, vl);
|
||||
auto vmask_u8mf4 = __riscv_vle8_v_u8mf4(mask_row + jm, vlm);
|
||||
auto vmask_u32 = __riscv_vzext_vf4(vmask_u8mf4, vlm);
|
||||
// 0 -> 0000; 1 -> 1111
|
||||
vmask_u32 = __riscv_vmul(vmask_u32, 0b00000001000000010000000100000001, vlm);
|
||||
auto vmask_u8 = __riscv_vreinterpret_u8m1(vmask_u32);
|
||||
auto vec_pixel = __riscv_vzext_vf4(vec_pixel_u8, vl);
|
||||
auto vmask = __riscv_vmseq_vx_u8m1_b8(vmask_u8, 1, vl);
|
||||
vec_sum = __riscv_vwaddu_wv_u64m8_tumu(vmask, vec_sum, vec_sum, vec_pixel, vl);
|
||||
vec_sqsum = __riscv_vwmaccu_vv_u64m8_tumu(vmask, vec_sqsum, vec_pixel, vec_pixel, vl);
|
||||
nz += __riscv_vcpop_m_b8(vmask, vl);
|
||||
}
|
||||
}
|
||||
nz /= 4;
|
||||
} else {
|
||||
for (int i = 0; i < height; i++) {
|
||||
const uchar* src_row = src_data + i * src_step;
|
||||
int j = 0, vl;
|
||||
for ( ; j < width*4; j += vl) {
|
||||
vl = __riscv_vsetvl_e8m1(width*4 - j);
|
||||
auto vec_pixel_u8 = __riscv_vle8_v_u8m1(src_row + j, vl);
|
||||
auto vec_pixel = __riscv_vzext_vf4(vec_pixel_u8, vl);
|
||||
vec_sum = __riscv_vwaddu_wv_u64m8_tu(vec_sum, vec_sum, vec_pixel, vl);
|
||||
vec_sqsum = __riscv_vwmaccu_vv_u64m8_tu(vec_sqsum, vec_pixel, vec_pixel, vl);
|
||||
}
|
||||
}
|
||||
nz = height * width;
|
||||
}
|
||||
if (nz == 0) {
|
||||
if (mean_val) *mean_val = 0.0;
|
||||
if (stddev_val) *stddev_val = 0.0;
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
uint64_t s[256], sq[256], sum[4] = {0}, sqsum[4] = {0};
|
||||
__riscv_vse64(s, vec_sum, vlmax);
|
||||
__riscv_vse64(sq, vec_sqsum, vlmax);
|
||||
for (int i = 0; i < vlmax; ++i)
|
||||
{
|
||||
sum[i % 4] += s[i];
|
||||
sqsum[i % 4] += sq[i];
|
||||
}
|
||||
if (mean_val) {
|
||||
mean_val[0] = (double)sum[0] / nz;
|
||||
mean_val[1] = (double)sum[1] / nz;
|
||||
mean_val[2] = (double)sum[2] / nz;
|
||||
mean_val[3] = (double)sum[3] / nz;
|
||||
}
|
||||
if (stddev_val) {
|
||||
stddev_val[0] = std::sqrt(std::max(((double)sqsum[0] / nz) - (mean_val[0] * mean_val[0]), 0.0));
|
||||
stddev_val[1] = std::sqrt(std::max(((double)sqsum[1] / nz) - (mean_val[1] * mean_val[1]), 0.0));
|
||||
stddev_val[2] = std::sqrt(std::max(((double)sqsum[2] / nz) - (mean_val[2] * mean_val[2]), 0.0));
|
||||
stddev_val[3] = std::sqrt(std::max(((double)sqsum[3] / nz) - (mean_val[3] * mean_val[3]), 0.0));
|
||||
}
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
inline int meanStdDev_32FC1(const uchar* src_data, size_t src_step, int width, int height,
|
||||
double* mean_val, double* stddev_val, uchar* mask, size_t mask_step) {
|
||||
int nz = 0;
|
||||
int vlmax = __riscv_vsetvlmax_e64m4();
|
||||
vfloat64m4_t vec_sum = __riscv_vfmv_v_f_f64m4(0, vlmax);
|
||||
vfloat64m4_t vec_sqsum = __riscv_vfmv_v_f_f64m4(0, vlmax);
|
||||
src_step /= sizeof(float);
|
||||
if (mask) {
|
||||
for (int i = 0; i < height; ++i) {
|
||||
const float* src_row0 = reinterpret_cast<const float*>(src_data) + i * src_step;
|
||||
const uchar* mask_row = mask + i * mask_step;
|
||||
int j = 0, vl;
|
||||
for ( ; j < width; j += vl) {
|
||||
vl = __riscv_vsetvl_e32m2(width - j);
|
||||
auto vec_pixel = __riscv_vle32_v_f32m2(src_row0 + j, vl);
|
||||
auto vmask_u8 = __riscv_vle8_v_u8mf2(mask_row + j, vl);
|
||||
auto vmask_u32 = __riscv_vzext_vf4(vmask_u8, vl);
|
||||
auto vmask = __riscv_vmseq_vx_u32m2_b16(vmask_u32, 1, vl);
|
||||
vec_sum = __riscv_vfwadd_wv_f64m4_tumu(vmask, vec_sum, vec_sum, vec_pixel, vl);
|
||||
vec_sqsum = __riscv_vfwmacc_vv_f64m4_tumu(vmask, vec_sqsum, vec_pixel, vec_pixel, vl);
|
||||
nz += __riscv_vcpop_m_b16(vmask, vl);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < height; i++) {
|
||||
const float* src_row0 = reinterpret_cast<const float*>(src_data) + i * src_step;
|
||||
int j = 0, vl;
|
||||
for ( ; j < width; j += vl) {
|
||||
vl = __riscv_vsetvl_e32m2(width - j);
|
||||
auto vec_pixel = __riscv_vle32_v_f32m2(src_row0 + j, vl);
|
||||
vec_sum = __riscv_vfwadd_wv_f64m4_tu(vec_sum, vec_sum, vec_pixel, vl);
|
||||
vec_sqsum = __riscv_vfwmacc_vv_f64m4_tu(vec_sqsum, vec_pixel, vec_pixel, vl);
|
||||
}
|
||||
}
|
||||
nz = height * width;
|
||||
}
|
||||
if (nz == 0) {
|
||||
if (mean_val) *mean_val = 0.0;
|
||||
if (stddev_val) *stddev_val = 0.0;
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
auto zero = __riscv_vfmv_v_f_f64m1(0, vlmax);
|
||||
auto vec_red = __riscv_vfmv_v_f_f64m1(0, vlmax);
|
||||
auto vec_reddev = __riscv_vfmv_v_f_f64m1(0, vlmax);
|
||||
vec_red = __riscv_vfredusum(vec_sum, zero, vlmax);
|
||||
vec_reddev = __riscv_vfredusum(vec_sqsum, zero, vlmax);
|
||||
double sum = __riscv_vfmv_f(vec_red);
|
||||
double mean = sum / nz;
|
||||
if (mean_val) {
|
||||
*mean_val = mean;
|
||||
}
|
||||
if (stddev_val) {
|
||||
double sqsum = __riscv_vfmv_f(vec_reddev);
|
||||
double variance = std::max((sqsum / nz) - (mean * mean), 0.0);
|
||||
double stddev = std::sqrt(variance);
|
||||
*stddev_val = stddev;
|
||||
}
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+63
-32
@@ -20,9 +20,9 @@ namespace cv { namespace cv_hal_rvv {
|
||||
#if defined __GNUC__
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
static int merge8u(const uchar** src, uchar* dst, int len, int cn ) {
|
||||
inline int merge8u(const uchar** src, uchar* dst, int len, int cn ) {
|
||||
int k = cn % 4 ? cn % 4 : 4;
|
||||
int i = 0, j;
|
||||
int i = 0;
|
||||
int vl = __riscv_vsetvlmax_e8m1();
|
||||
if( k == 1 )
|
||||
{
|
||||
@@ -30,7 +30,7 @@ static int merge8u(const uchar** src, uchar* dst, int len, int cn ) {
|
||||
for( ; i <= len - vl; i += vl)
|
||||
{
|
||||
auto a = __riscv_vle8_v_u8m1(src0 + i, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn, sizeof(uchar)*2, a, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn, sizeof(uchar)*cn, a, vl);
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize(disable)
|
||||
@@ -45,8 +45,8 @@ static int merge8u(const uchar** src, uchar* dst, int len, int cn ) {
|
||||
{
|
||||
auto a = __riscv_vle8_v_u8m1(src0 + i, vl);
|
||||
auto b = __riscv_vle8_v_u8m1(src1 + i, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn, sizeof(uchar)*2, a, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 1, sizeof(uchar)*2, b, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn, sizeof(uchar)*cn, a, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 1, sizeof(uchar)*cn, b, vl);
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize(disable)
|
||||
@@ -65,9 +65,9 @@ static int merge8u(const uchar** src, uchar* dst, int len, int cn ) {
|
||||
auto a = __riscv_vle8_v_u8m1(src0 + i, vl);
|
||||
auto b = __riscv_vle8_v_u8m1(src1 + i, vl);
|
||||
auto c = __riscv_vle8_v_u8m1(src2 + i, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn, sizeof(uchar)*3, a, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 1, sizeof(uchar)*3, b, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 2, sizeof(uchar)*3, c, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn, sizeof(uchar)*cn, a, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 1, sizeof(uchar)*cn, b, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 2, sizeof(uchar)*cn, c, vl);
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize(disable)
|
||||
@@ -88,10 +88,10 @@ static int merge8u(const uchar** src, uchar* dst, int len, int cn ) {
|
||||
auto b = __riscv_vle8_v_u8m1(src1 + i, vl);
|
||||
auto c = __riscv_vle8_v_u8m1(src2 + i, vl);
|
||||
auto d = __riscv_vle8_v_u8m1(src3 + i, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn, sizeof(uchar)*4, a, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 1, sizeof(uchar)*4, b, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 2, sizeof(uchar)*4, c, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 3, sizeof(uchar)*4, d, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn, sizeof(uchar)*cn, a, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 1, sizeof(uchar)*cn, b, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 2, sizeof(uchar)*cn, c, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + i*cn + 3, sizeof(uchar)*cn, d, vl);
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize(disable)
|
||||
@@ -110,10 +110,27 @@ static int merge8u(const uchar** src, uchar* dst, int len, int cn ) {
|
||||
for( ; k < cn; k += 4 )
|
||||
{
|
||||
const uchar *src0 = src[k], *src1 = src[k+1], *src2 = src[k+2], *src3 = src[k+3];
|
||||
for( i = 0, j = k; i < len; i++, j += cn )
|
||||
i = 0;
|
||||
for( ; i <= len - vl; i += vl)
|
||||
{
|
||||
dst[j] = src0[i]; dst[j+1] = src1[i];
|
||||
dst[j+2] = src2[i]; dst[j+3] = src3[i];
|
||||
auto a = __riscv_vle8_v_u8m1(src0 + i, vl);
|
||||
auto b = __riscv_vle8_v_u8m1(src1 + i, vl);
|
||||
auto c = __riscv_vle8_v_u8m1(src2 + i, vl);
|
||||
auto d = __riscv_vle8_v_u8m1(src3 + i, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + k+i*cn, sizeof(uchar)*cn, a, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + k+i*cn + 1, sizeof(uchar)*cn, b, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + k+i*cn + 2, sizeof(uchar)*cn, c, vl);
|
||||
__riscv_vsse8_v_u8m1(dst + k+i*cn + 3, sizeof(uchar)*cn, d, vl);
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize(disable)
|
||||
#endif
|
||||
for( ; i < len; i++ )
|
||||
{
|
||||
dst[k+i*cn] = src0[i];
|
||||
dst[k+i*cn+1] = src1[i];
|
||||
dst[k+i*cn+2] = src2[i];
|
||||
dst[k+i*cn+3] = src3[i];
|
||||
}
|
||||
}
|
||||
return CV_HAL_ERROR_OK;
|
||||
@@ -122,9 +139,9 @@ static int merge8u(const uchar** src, uchar* dst, int len, int cn ) {
|
||||
#if defined __GNUC__
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
static int merge16u(const ushort** src, ushort* dst, int len, int cn ) {
|
||||
inline int merge16u(const ushort** src, ushort* dst, int len, int cn ) {
|
||||
int k = cn % 4 ? cn % 4 : 4;
|
||||
int i = 0, j;
|
||||
int i = 0;
|
||||
int vl = __riscv_vsetvlmax_e16m1();
|
||||
if( k == 1 )
|
||||
{
|
||||
@@ -132,7 +149,7 @@ static int merge16u(const ushort** src, ushort* dst, int len, int cn ) {
|
||||
for( ; i <= len - vl; i += vl)
|
||||
{
|
||||
auto a = __riscv_vle16_v_u16m1(src0 + i, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn, sizeof(ushort)*2, a, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn, sizeof(ushort)*cn, a, vl);
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize(disable)
|
||||
@@ -147,8 +164,8 @@ static int merge16u(const ushort** src, ushort* dst, int len, int cn ) {
|
||||
{
|
||||
auto a = __riscv_vle16_v_u16m1(src0 + i, vl);
|
||||
auto b = __riscv_vle16_v_u16m1(src1 + i, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn, sizeof(ushort)*2, a, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 1, sizeof(ushort)*2, b, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn, sizeof(ushort)*cn, a, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 1, sizeof(ushort)*cn, b, vl);
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize(disable)
|
||||
@@ -167,9 +184,9 @@ static int merge16u(const ushort** src, ushort* dst, int len, int cn ) {
|
||||
auto a = __riscv_vle16_v_u16m1(src0 + i, vl);
|
||||
auto b = __riscv_vle16_v_u16m1(src1 + i, vl);
|
||||
auto c = __riscv_vle16_v_u16m1(src2 + i, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn, sizeof(ushort)*3, a, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 1, sizeof(ushort)*3, b, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 2, sizeof(ushort)*3, c, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn, sizeof(ushort)*cn, a, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 1, sizeof(ushort)*cn, b, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 2, sizeof(ushort)*cn, c, vl);
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize(disable)
|
||||
@@ -190,10 +207,10 @@ static int merge16u(const ushort** src, ushort* dst, int len, int cn ) {
|
||||
auto b = __riscv_vle16_v_u16m1(src1 + i, vl);
|
||||
auto c = __riscv_vle16_v_u16m1(src2 + i, vl);
|
||||
auto d = __riscv_vle16_v_u16m1(src3 + i, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn, sizeof(ushort)*4, a, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 1, sizeof(ushort)*4, b, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 2, sizeof(ushort)*4, c, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 3, sizeof(ushort)*4, d, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn, sizeof(ushort)*cn, a, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 1, sizeof(ushort)*cn, b, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 2, sizeof(ushort)*cn, c, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + i*cn + 3, sizeof(ushort)*cn, d, vl);
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize(disable)
|
||||
@@ -212,10 +229,24 @@ static int merge16u(const ushort** src, ushort* dst, int len, int cn ) {
|
||||
for( ; k < cn; k += 4 )
|
||||
{
|
||||
const uint16_t *src0 = src[k], *src1 = src[k+1], *src2 = src[k+2], *src3 = src[k+3];
|
||||
for( i = 0, j = k; i < len; i++, j += cn )
|
||||
i = 0;
|
||||
for( ; i <= len - vl; i += vl)
|
||||
{
|
||||
dst[j] = src0[i]; dst[j+1] = src1[i];
|
||||
dst[j+2] = src2[i]; dst[j+3] = src3[i];
|
||||
auto a = __riscv_vle16_v_u16m1(src0 + i, vl);
|
||||
auto b = __riscv_vle16_v_u16m1(src1 + i, vl);
|
||||
auto c = __riscv_vle16_v_u16m1(src2 + i, vl);
|
||||
auto d = __riscv_vle16_v_u16m1(src3 + i, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + k+i*cn, sizeof(ushort)*cn, a, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + k+i*cn + 1, sizeof(ushort)*cn, b, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + k+i*cn + 2, sizeof(ushort)*cn, c, vl);
|
||||
__riscv_vsse16_v_u16m1(dst + k+i*cn + 3, sizeof(ushort)*cn, d, vl);
|
||||
}
|
||||
for( ; i < len; i++ )
|
||||
{
|
||||
dst[k+i*cn] = src0[i];
|
||||
dst[k+i*cn+1] = src1[i];
|
||||
dst[k+i*cn+2] = src2[i];
|
||||
dst[k+i*cn+3] = src3[i];
|
||||
}
|
||||
}
|
||||
return CV_HAL_ERROR_OK;
|
||||
@@ -224,7 +255,7 @@ static int merge16u(const ushort** src, ushort* dst, int len, int cn ) {
|
||||
#if defined __GNUC__
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
static int merge32s(const int** src, int* dst, int len, int cn ) {
|
||||
inline int merge32s(const int** src, int* dst, int len, int cn ) {
|
||||
int k = cn % 4 ? cn % 4 : 4;
|
||||
int i, j;
|
||||
if( k == 1 )
|
||||
@@ -294,7 +325,7 @@ static int merge32s(const int** src, int* dst, int len, int cn ) {
|
||||
#if defined __GNUC__
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
static int merge64s(const int64** src, int64* dst, int len, int cn ) {
|
||||
inline int merge64s(const int64** src, int64* dst, int len, int cn ) {
|
||||
int k = cn % 4 ? cn % 4 : 4;
|
||||
int i, j;
|
||||
if( k == 1 )
|
||||
|
||||
Vendored
+5
-1
@@ -3,5 +3,9 @@ project(kleidicv_hal)
|
||||
if(HAVE_KLEIDICV)
|
||||
option(KLEIDICV_ENABLE_SME2 "" OFF) # not compatible with some CLang versions in NDK
|
||||
include("${KLEIDICV_SOURCE_PATH}/adapters/opencv/CMakeLists.txt")
|
||||
# HACK to suppress adapters/opencv/kleidicv_hal.cpp:343:12: warning: unused function 'from_opencv' [-Wunused-function]
|
||||
target_compile_options( kleidicv_hal PRIVATE
|
||||
$<TARGET_PROPERTY:kleidicv,COMPILE_OPTIONS>
|
||||
"-Wno-old-style-cast" "-Wno-unused-function"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -1,8 +1,8 @@
|
||||
function(download_kleidicv root_var)
|
||||
set(${root_var} "" PARENT_SCOPE)
|
||||
|
||||
ocv_update(KLEIDICV_SRC_COMMIT "0.2.0")
|
||||
ocv_update(KLEIDICV_SRC_HASH "dabe522e8f55ac342d07a787391dab80")
|
||||
ocv_update(KLEIDICV_SRC_COMMIT "0.3.0")
|
||||
ocv_update(KLEIDICV_SRC_HASH "51a77b0185c2bac2a968a2163869b1ed")
|
||||
|
||||
set(THE_ROOT "${OpenCV_BINARY_DIR}/3rdparty/kleidicv")
|
||||
ocv_download(FILENAME "kleidicv-${KLEIDICV_SRC_COMMIT}.tar.gz"
|
||||
|
||||
@@ -233,6 +233,8 @@ OCV_OPTION(WITH_NDSRVP "Use Andes RVP extension" (NOT CV_DISABLE_OPTIMIZATION)
|
||||
VISIBLE_IF RISCV)
|
||||
OCV_OPTION(WITH_HAL_RVV "Use HAL RVV optimizations" (NOT CV_DISABLE_OPTIMIZATION)
|
||||
VISIBLE_IF RISCV)
|
||||
OCV_OPTION(WITH_FASTCV "Use Qualcomm FastCV acceleration library for ARM platform" OFF
|
||||
VISIBLE_IF ((ARM OR AARCH64) AND (ANDROID OR (UNIX AND NOT APPLE AND NOT IOS AND NOT XROS))))
|
||||
OCV_OPTION(WITH_CPUFEATURES "Use cpufeatures Android library" ON
|
||||
VISIBLE_IF ANDROID
|
||||
VERIFY HAVE_CPUFEATURES)
|
||||
@@ -304,6 +306,9 @@ OCV_OPTION(WITH_OPENJPEG "Include JPEG2K support (OpenJPEG)" ON
|
||||
OCV_OPTION(WITH_JPEG "Include JPEG support" ON
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY HAVE_JPEG)
|
||||
OCV_OPTION(WITH_JPEGXL "Include JPEG XL support" OFF
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY HAVE_JPEGXL)
|
||||
OCV_OPTION(WITH_WEBP "Include WebP support" ON
|
||||
VISIBLE_IF NOT WINRT
|
||||
VERIFY HAVE_WEBP)
|
||||
@@ -430,6 +435,9 @@ OCV_OPTION(WITH_ITT "Include Intel ITT support" ON
|
||||
OCV_OPTION(WITH_PROTOBUF "Enable libprotobuf" ON
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY HAVE_PROTOBUF)
|
||||
OCV_OPTION(WITH_IMGCODEC_GIF "Include GIF support" OFF
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY HAVE_IMGCODEC_GIF)
|
||||
OCV_OPTION(WITH_IMGCODEC_HDR "Include HDR support" ON
|
||||
VISIBLE_IF TRUE
|
||||
VERIFY HAVE_IMGCODEC_HDR)
|
||||
@@ -935,6 +943,13 @@ if(HAVE_OPENVX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(HAVE_FASTCV)
|
||||
ocv_debug_message(STATUS "Enable FastCV acceleration")
|
||||
if(NOT ";${OpenCV_HAL};" MATCHES ";fastcv;")
|
||||
set(OpenCV_HAL "fastcv;${OpenCV_HAL}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(HAVE_KLEIDICV)
|
||||
ocv_debug_message(STATUS "Enable KleidiCV acceleration")
|
||||
if(NOT ";${OpenCV_HAL};" MATCHES ";kleidicv;")
|
||||
@@ -972,6 +987,14 @@ foreach(hal ${OpenCV_HAL})
|
||||
else()
|
||||
message(STATUS "Carotene: NEON is not available, disabling carotene...")
|
||||
endif()
|
||||
elseif(hal STREQUAL "fastcv")
|
||||
if((ARM OR AARCH64) AND (ANDROID OR (UNIX AND NOT APPLE AND NOT IOS AND NOT XROS)))
|
||||
add_subdirectory(3rdparty/fastcv)
|
||||
ocv_hal_register(FASTCV_HAL_LIBRARIES FASTCV_HAL_HEADERS FASTCV_HAL_INCLUDE_DIRS)
|
||||
list(APPEND OpenCV_USED_HAL "fastcv (ver ${FASTCV_HAL_VERSION})")
|
||||
else()
|
||||
message(STATUS "FastCV: fastcv is not available, disabling fastcv...")
|
||||
endif()
|
||||
elseif(hal STREQUAL "kleidicv")
|
||||
add_subdirectory(3rdparty/kleidicv)
|
||||
ocv_hal_register(KLEIDICV_HAL_LIBRARIES KLEIDICV_HAL_HEADERS KLEIDICV_HAL_INCLUDE_DIRS)
|
||||
@@ -1513,6 +1536,10 @@ if(WITH_TIFF OR HAVE_TIFF)
|
||||
status(" TIFF:" TIFF_FOUND THEN "${TIFF_LIBRARY} (ver ${TIFF_VERSION} / ${TIFF_VERSION_STRING})" ELSE "build (ver ${TIFF_VERSION} - ${TIFF_VERSION_STRING})")
|
||||
endif()
|
||||
|
||||
if(WITH_JPEGXL OR HAVE_JPEGXL)
|
||||
status(" JPEG XL:" JPEGXL_FOUND THEN "${JPEGXL_LIBRARY} (ver ${JPEGXL_VERSION})" ELSE "NO")
|
||||
endif()
|
||||
|
||||
if(HAVE_OPENJPEG)
|
||||
status(" JPEG 2000:" OpenJPEG_FOUND
|
||||
THEN "OpenJPEG (ver ${OPENJPEG_VERSION})"
|
||||
@@ -1540,6 +1567,10 @@ if(WITH_GDCM OR HAVE_GDCM)
|
||||
status(" GDCM:" HAVE_GDCM THEN "YES (${GDCM_VERSION})" ELSE "NO")
|
||||
endif()
|
||||
|
||||
if(WITH_IMGCODEC_GIF OR DEFINED HAVE_IMGCODEC_GIF)
|
||||
status(" GIF:" HAVE_IMGCODEC_GIF THEN "YES" ELSE "NO")
|
||||
endif()
|
||||
|
||||
if(WITH_IMGCODEC_HDR OR DEFINED HAVE_IMGCODEC_HDR)
|
||||
status(" HDR:" HAVE_IMGCODEC_HDR THEN "YES" ELSE "NO")
|
||||
endif()
|
||||
@@ -1793,6 +1824,9 @@ endif()
|
||||
if(WITH_OPENVX OR HAVE_OPENVX)
|
||||
status(" OpenVX:" HAVE_OPENVX THEN "YES (${OPENVX_LIBRARIES})" ELSE "NO")
|
||||
endif()
|
||||
if(WITH_FASTCV OR HAVE_FASTCV)
|
||||
status(" FastCV:" HAVE_FASTCV THEN "YES (${FASTCV_LIBRARY})" ELSE "NO")
|
||||
endif()
|
||||
|
||||
status(" Custom HAL:" OpenCV_USED_HAL THEN "YES (${OpenCV_USED_HAL})" ELSE "NO")
|
||||
|
||||
|
||||
@@ -766,7 +766,6 @@ CvBackgroundData* icvCreateBackgroundData( const char* filename, Size winsize )
|
||||
}
|
||||
if( count > 0 )
|
||||
{
|
||||
//rewind( input );
|
||||
fseek( input, 0, SEEK_SET );
|
||||
datasize += sizeof( *data ) + sizeof( char* ) * count;
|
||||
data = (CvBackgroundData*) fastMalloc( datasize );
|
||||
@@ -872,8 +871,6 @@ void icvGetNextFromBackgroundData( CvBackgroundData* data,
|
||||
|
||||
reader->src = img;
|
||||
|
||||
//reader->offset.x = round % data->winsize.width;
|
||||
//reader->offset.y = round / data->winsize.width;
|
||||
reader->offset = offset;
|
||||
reader->point = reader->offset;
|
||||
reader->scale = MAX(
|
||||
|
||||
@@ -191,11 +191,6 @@ if(CV_GCC OR CV_CLANG OR CV_ICX)
|
||||
endif()
|
||||
add_extra_compiler_option(-fdiagnostics-show-option)
|
||||
|
||||
# The -Wno-long-long is required in 64bit systems when including system headers.
|
||||
if(X86_64)
|
||||
add_extra_compiler_option(-Wno-long-long)
|
||||
endif()
|
||||
|
||||
# We need pthread's, unless we have explicitly disabled multi-thread execution.
|
||||
if(NOT OPENCV_DISABLE_THREAD_SUPPORT
|
||||
AND (
|
||||
@@ -409,6 +404,14 @@ if(NOT OPENCV_SKIP_LINK_NO_UNDEFINED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# For 16k pages support with NDK prior 27
|
||||
# Details: https://developer.android.com/guide/practices/page-sizes?hl=en
|
||||
if(ANDROID AND ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES AND (ANDROID_ABI STREQUAL arm64-v8a OR ANDROID_ABI STREQUAL x86_64))
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
|
||||
endif()
|
||||
|
||||
# combine all "extra" options
|
||||
if(NOT OPENCV_SKIP_EXTRA_COMPILER_FLAGS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_C_FLAGS}")
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
# The script is taken from https://webkit.googlesource.com/WebKit/+/master/Source/cmake/FindJPEGXL.cmake
|
||||
|
||||
# Copyright (C) 2021 Sony Interactive Entertainment Inc.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
||||
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
# THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#[=======================================================================[.rst:
|
||||
FindJPEGXL
|
||||
---------
|
||||
Find JPEGXL headers and libraries.
|
||||
Imported Targets
|
||||
^^^^^^^^^^^^^^^^
|
||||
``JPEGXL::jxl``
|
||||
The JPEGXL library, if found.
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
This will define the following variables in your project:
|
||||
``JPEGXL_FOUND``
|
||||
true if (the requested version of) JPEGXL is available.
|
||||
``JPEGXL_VERSION``
|
||||
the version of JPEGXL.
|
||||
``JPEGXL_LIBRARIES``
|
||||
the libraries to link against to use JPEGXL.
|
||||
``JPEGXL_INCLUDE_DIRS``
|
||||
where to find the JPEGXL headers.
|
||||
``JPEGXL_COMPILE_OPTIONS``
|
||||
this should be passed to target_compile_options(), if the
|
||||
target is not used for linking
|
||||
#]=======================================================================]
|
||||
|
||||
if(NOT OPENCV_SKIP_JPEGXL_FIND_PACKAGE)
|
||||
find_package(PkgConfig QUIET)
|
||||
if (PkgConfig_FOUND)
|
||||
pkg_check_modules(PC_JPEGXL QUIET jxl)
|
||||
set(JPEGXL_COMPILE_OPTIONS ${PC_JPEGXL_CFLAGS_OTHER})
|
||||
set(JPEGXL_VERSION ${PC_JPEGXL_VERSION})
|
||||
endif ()
|
||||
find_path(JPEGXL_INCLUDE_DIR
|
||||
NAMES jxl/decode.h
|
||||
HINTS ${PC_JPEGXL_INCLUDEDIR} ${PC_JPEGXL_INCLUDE_DIRS} ${JPEGXL_INCLUDE_DIR}
|
||||
)
|
||||
find_library(JPEGXL_LIBRARY
|
||||
NAMES ${JPEGXL_NAMES} jxl
|
||||
HINTS ${PC_JPEGXL_LIBDIR} ${PC_JPEGXL_LIBRARY_DIRS}
|
||||
)
|
||||
find_library(JPEGXL_CMS_LIBRARY
|
||||
NAMES ${JPEGXL_NAMES} jxl_cms
|
||||
HINTS ${PC_JPEGXL_LIBDIR} ${PC_JPEGXL_LIBRARY_DIRS}
|
||||
)
|
||||
if (JPEGXL_LIBRARY AND JPEGXL_CMS_LIBRARY)
|
||||
set(JPEGXL_LIBRARY ${JPEGXL_LIBRARY} ${JPEGXL_CMS_LIBRARY})
|
||||
endif ()
|
||||
find_library(JPEGXL_CMS2_LIBRARY
|
||||
NAMES ${JPEGXL_NAMES} lcms2
|
||||
HINTS ${PC_JPEGXL_LIBDIR} ${PC_JPEGXL_LIBRARY_DIRS}
|
||||
)
|
||||
if (JPEGXL_LIBRARY AND JPEGXL_CMS2_LIBRARY)
|
||||
set(JPEGXL_LIBRARY ${JPEGXL_LIBRARY} ${JPEGXL_CMS2_LIBRARY})
|
||||
endif ()
|
||||
find_library(JPEGXL_THREADS_LIBRARY
|
||||
NAMES ${JPEGXL_NAMES} jxl_threads
|
||||
HINTS ${PC_JPEGXL_LIBDIR} ${PC_JPEGXL_LIBRARY_DIRS}
|
||||
)
|
||||
if (JPEGXL_LIBRARY AND JPEGXL_THREADS_LIBRARY)
|
||||
set(JPEGXL_LIBRARY ${JPEGXL_LIBRARY} ${JPEGXL_THREADS_LIBRARY})
|
||||
endif ()
|
||||
find_library(JPEGXL_BROTLICOMMON_LIBRARY
|
||||
NAMES ${JPEGXL_NAMES} brotlicommon
|
||||
HINTS ${PC_JPEGXL_LIBDIR} ${PC_JPEGXL_LIBRARY_DIRS}
|
||||
)
|
||||
find_library(JPEGXL_BROTLIDEC_LIBRARY
|
||||
NAMES ${JPEGXL_NAMES} brotlidec
|
||||
HINTS ${PC_JPEGXL_LIBDIR} ${PC_JPEGXL_LIBRARY_DIRS}
|
||||
)
|
||||
if (JPEGXL_LIBRARY AND JPEGXL_BROTLIDEC_LIBRARY)
|
||||
set(JPEGXL_LIBRARY ${JPEGXL_LIBRARY} ${JPEGXL_BROTLIDEC_LIBRARY})
|
||||
endif ()
|
||||
find_library(JPEGXL_BROTLIENC_LIBRARY
|
||||
NAMES ${JPEGXL_NAMES} brotlienc
|
||||
HINTS ${PC_JPEGXL_LIBDIR} ${PC_JPEGXL_LIBRARY_DIRS}
|
||||
)
|
||||
if (JPEGXL_LIBRARY AND JPEGXL_BROTLIENC_LIBRARY)
|
||||
set(JPEGXL_LIBRARY ${JPEGXL_LIBRARY} ${JPEGXL_BROTLIENC_LIBRARY})
|
||||
endif ()
|
||||
if (JPEGXL_LIBRARY AND JPEGXL_BROTLICOMMON_LIBRARY)
|
||||
set(JPEGXL_LIBRARY ${JPEGXL_LIBRARY} ${JPEGXL_BROTLICOMMON_LIBRARY})
|
||||
endif ()
|
||||
find_library(JPEGXL_HWY_LIBRARY
|
||||
NAMES ${JPEGXL_NAMES} hwy
|
||||
HINTS ${PC_JPEGXL_LIBDIR} ${PC_JPEGXL_LIBRARY_DIRS}
|
||||
)
|
||||
if (JPEGXL_LIBRARY AND JPEGXL_HWY_LIBRARY)
|
||||
set(JPEGXL_LIBRARY ${JPEGXL_LIBRARY} ${JPEGXL_HWY_LIBRARY})
|
||||
endif ()
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(JPEGXL
|
||||
FOUND_VAR JPEGXL_FOUND
|
||||
REQUIRED_VARS JPEGXL_LIBRARY JPEGXL_INCLUDE_DIR
|
||||
VERSION_VAR JPEGXL_VERSION
|
||||
)
|
||||
if (NOT EXISTS "${JPEGXL_INCLUDE_DIR}/jxl/version.h")
|
||||
# the library version older 0.6 is not supported (no version.h file there)
|
||||
set(JPEGXL_FOUND FALSE CACHE BOOL "libjxl found" FORCE)
|
||||
message(STATUS "Ignored incompatible version of libjxl")
|
||||
endif ()
|
||||
|
||||
if (JPEGXL_LIBRARY AND NOT TARGET JPEGXL::jxl)
|
||||
add_library(JPEGXL::jxl UNKNOWN IMPORTED GLOBAL)
|
||||
set_target_properties(JPEGXL::jxl PROPERTIES
|
||||
IMPORTED_LOCATION "${JPEGXL_LIBRARY}"
|
||||
INTERFACE_COMPILE_OPTIONS "${JPEGXL_COMPILE_OPTIONS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${JPEGXL_INCLUDE_DIR}"
|
||||
)
|
||||
endif ()
|
||||
mark_as_advanced(JPEGXL_INCLUDE_DIR JPEGXL_LIBRARY)
|
||||
if (JPEGXL_FOUND)
|
||||
set(JPEGXL_LIBRARIES ${JPEGXL_LIBRARY})
|
||||
set(JPEGXL_INCLUDE_DIRS ${JPEGXL_INCLUDE_DIR})
|
||||
if (NOT JPEGXL_VERSION)
|
||||
file(READ "${JPEGXL_INCLUDE_DIR}/jxl/version.h" VERSION_HEADER_CONTENTS)
|
||||
string(REGEX MATCH "#define JPEGXL_MAJOR_VERSION ([0-9]+)" _ ${VERSION_HEADER_CONTENTS})
|
||||
set(JXL_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||
string(REGEX MATCH "#define JPEGXL_MINOR_VERSION ([0-9]+)" _ ${VERSION_HEADER_CONTENTS})
|
||||
set(JXL_VERSION_MINOR ${CMAKE_MATCH_1})
|
||||
string(REGEX MATCH "#define JPEGXL_PATCH_VERSION ([0-9]+)" _ ${VERSION_HEADER_CONTENTS})
|
||||
set(JXL_VERSION_PATCH ${CMAKE_MATCH_1})
|
||||
set(JPEGXL_VERSION "${JXL_VERSION_MAJOR}.${JXL_VERSION_MINOR}.${JXL_VERSION_PATCH}")
|
||||
endif()
|
||||
endif ()
|
||||
endif()
|
||||
@@ -196,19 +196,45 @@ if(WITH_WEBP AND NOT WEBP_FOUND
|
||||
endif()
|
||||
|
||||
if(NOT WEBP_VERSION AND WEBP_INCLUDE_DIR)
|
||||
ocv_clear_vars(ENC_MAJ_VERSION ENC_MIN_VERSION ENC_REV_VERSION)
|
||||
if(EXISTS "${WEBP_INCLUDE_DIR}/enc/vp8enci.h")
|
||||
ocv_parse_header("${WEBP_INCLUDE_DIR}/enc/vp8enci.h" WEBP_VERSION_LINES ENC_MAJ_VERSION ENC_MIN_VERSION ENC_REV_VERSION)
|
||||
set(WEBP_VERSION "${ENC_MAJ_VERSION}.${ENC_MIN_VERSION}.${ENC_REV_VERSION}")
|
||||
elseif(EXISTS "${WEBP_INCLUDE_DIR}/webp/encode.h")
|
||||
if(EXISTS "${WEBP_INCLUDE_DIR}/webp/encode.h")
|
||||
file(STRINGS "${WEBP_INCLUDE_DIR}/webp/encode.h" WEBP_ENCODER_ABI_VERSION REGEX "#define[ \t]+WEBP_ENCODER_ABI_VERSION[ \t]+([x0-9a-f]+)" )
|
||||
if(WEBP_ENCODER_ABI_VERSION MATCHES "#define[ \t]+WEBP_ENCODER_ABI_VERSION[ \t]+([x0-9a-f]+)")
|
||||
set(WEBP_ENCODER_ABI_VERSION "${CMAKE_MATCH_1}")
|
||||
set(WEBP_VERSION "encoder: ${WEBP_ENCODER_ABI_VERSION}")
|
||||
else()
|
||||
unset(WEBP_ENCODER_ABI_VERSION)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(EXISTS "${WEBP_INCLUDE_DIR}/webp/decode.h")
|
||||
file(STRINGS "${WEBP_INCLUDE_DIR}/webp/decode.h" WEBP_DECODER_ABI_VERSION REGEX "#define[ \t]+WEBP_DECODER_ABI_VERSION[ \t]+([x0-9a-f]+)" )
|
||||
if(WEBP_DECODER_ABI_VERSION MATCHES "#define[ \t]+WEBP_DECODER_ABI_VERSION[ \t]+([x0-9a-f]+)")
|
||||
set(WEBP_DECODER_ABI_VERSION "${CMAKE_MATCH_1}")
|
||||
else()
|
||||
unset(WEBP_DECODER_ABI_VERSION)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(EXISTS "${WEBP_INCLUDE_DIR}/webp/demux.h")
|
||||
file(STRINGS "${WEBP_INCLUDE_DIR}/webp/demux.h" WEBP_DEMUX_ABI_VERSION REGEX "#define[ \t]+WEBP_DEMUX_ABI_VERSION[ \t]+([x0-9a-f]+)" )
|
||||
if(WEBP_DEMUX_ABI_VERSION MATCHES "#define[ \t]+WEBP_DEMUX_ABI_VERSION[ \t]+([x0-9a-f]+)")
|
||||
set(WEBP_DEMUX_ABI_VERSION "${CMAKE_MATCH_1}")
|
||||
else()
|
||||
unset(WEBP_DEMUX_ABI_VERSION)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(WEBP_VERSION "decoder: ${WEBP_DECODER_ABI_VERSION}, encoder: ${WEBP_ENCODER_ABI_VERSION}, demux: ${WEBP_DEMUX_ABI_VERSION}")
|
||||
endif()
|
||||
|
||||
# --- libjxl (optional) ---
|
||||
if(WITH_JPEGXL)
|
||||
ocv_clear_vars(HAVE_JPEGXL)
|
||||
ocv_clear_internal_cache_vars(JPEGXL_INCLUDE_PATHS JPEGXL_LIBRARIES JPEGXL_VERSION)
|
||||
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindJPEGXL.cmake")
|
||||
if(JPEGXL_FOUND)
|
||||
set(HAVE_JPEGXL YES)
|
||||
message(STATUS "Found system JPEG-XL: ver ${JPEGXL_VERSION}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --- libopenjp2 (optional, check before libjasper) ---
|
||||
@@ -371,6 +397,11 @@ if(WITH_GDCM)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_IMGCODEC_GIF)
|
||||
set(HAVE_IMGCODEC_GIF ON)
|
||||
elseif(DEFINED WITH_IMGCODEC_GIF)
|
||||
set(HAVE_IMGCODEC_GIF OFF)
|
||||
endif()
|
||||
if(WITH_IMGCODEC_HDR)
|
||||
set(HAVE_IMGCODEC_HDR ON)
|
||||
elseif(DEFINED WITH_IMGCODEC_HDR)
|
||||
|
||||
@@ -176,3 +176,27 @@ if(WITH_KLEIDICV)
|
||||
endif()
|
||||
endif()
|
||||
endif(WITH_KLEIDICV)
|
||||
|
||||
# --- FastCV ---
|
||||
if(WITH_FASTCV)
|
||||
if((EXISTS ${FastCV_INCLUDE_PATH}) AND (EXISTS ${FastCV_LIB_PATH}))
|
||||
message(STATUS "Use external FastCV ${FastCV_INCLUDE_PATH}, ${FastCV_LIB_PATH}")
|
||||
set(HAVE_FASTCV TRUE CACHE BOOL "FastCV status")
|
||||
else()
|
||||
include("${OpenCV_SOURCE_DIR}/3rdparty/fastcv/fastcv.cmake")
|
||||
set(FCV_ROOT_DIR "${OpenCV_BINARY_DIR}/3rdparty/fastcv")
|
||||
download_fastcv(${FCV_ROOT_DIR})
|
||||
if(HAVE_FASTCV)
|
||||
set(FastCV_INCLUDE_PATH "${FCV_ROOT_DIR}/inc" CACHE PATH "FastCV includes directory")
|
||||
set(FastCV_LIB_PATH "${FCV_ROOT_DIR}/libs" CACHE PATH "FastCV library directory")
|
||||
ocv_install_3rdparty_licenses(FastCV "${OpenCV_BINARY_DIR}/3rdparty/fastcv/LICENSE")
|
||||
install(FILES "${FastCV_LIB_PATH}/libfastcvopt.so"
|
||||
DESTINATION "${OPENCV_LIB_INSTALL_PATH}" COMPONENT "bin")
|
||||
else()
|
||||
set(HAVE_FASTCV FALSE CACHE BOOL "FastCV status")
|
||||
endif()
|
||||
endif()
|
||||
if(HAVE_FASTCV)
|
||||
set(FASTCV_LIBRARY "${FastCV_LIB_PATH}/libfastcvopt.so" CACHE PATH "FastCV library")
|
||||
endif()
|
||||
endif(WITH_FASTCV)
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
# Look for the header file.
|
||||
|
||||
unset(WEBP_FOUND)
|
||||
|
||||
FIND_PATH(WEBP_INCLUDE_DIR NAMES webp/decode.h)
|
||||
|
||||
if(NOT WEBP_INCLUDE_DIR)
|
||||
@@ -21,13 +19,14 @@ else()
|
||||
|
||||
# Look for the library.
|
||||
FIND_LIBRARY(WEBP_LIBRARY NAMES webp)
|
||||
MARK_AS_ADVANCED(WEBP_LIBRARY)
|
||||
FIND_LIBRARY(WEBP_MUX_LIBRARY NAMES webpmux)
|
||||
FIND_LIBRARY(WEBP_DEMUX_LIBRARY NAMES webpdemux)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set WEBP_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WebP DEFAULT_MSG WEBP_LIBRARY WEBP_INCLUDE_DIR)
|
||||
|
||||
SET(WEBP_LIBRARIES ${WEBP_LIBRARY})
|
||||
SET(WEBP_LIBRARIES ${WEBP_LIBRARY} ${WEBP_MUX_LIBRARY} ${WEBP_DEMUX_LIBRARY})
|
||||
SET(WEBP_INCLUDE_DIRS ${WEBP_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# https://developer.android.com/studio/releases/gradle-plugin
|
||||
set(ANDROID_GRADLE_PLUGIN_VERSION "7.3.1" CACHE STRING "Android Gradle Plugin version")
|
||||
set(ANDROID_GRADLE_PLUGIN_VERSION "8.6.0" CACHE STRING "Android Gradle Plugin version")
|
||||
message(STATUS "Android Gradle Plugin version: ${ANDROID_GRADLE_PLUGIN_VERSION}")
|
||||
|
||||
set(KOTLIN_PLUGIN_VERSION "1.8.20" CACHE STRING "Kotlin Plugin version")
|
||||
@@ -13,16 +13,16 @@ else()
|
||||
set(KOTLIN_STD_LIB "" CACHE STRING "Kotlin Standard Library dependency")
|
||||
endif()
|
||||
|
||||
set(GRADLE_VERSION "7.6.3" CACHE STRING "Gradle version")
|
||||
set(GRADLE_VERSION "8.11.1" CACHE STRING "Gradle version")
|
||||
message(STATUS "Gradle version: ${GRADLE_VERSION}")
|
||||
|
||||
set(ANDROID_COMPILE_SDK_VERSION "31" CACHE STRING "Android compileSdkVersion")
|
||||
set(ANDROID_COMPILE_SDK_VERSION "34" CACHE STRING "Android compileSdkVersion")
|
||||
if(ANDROID_NATIVE_API_LEVEL GREATER 21)
|
||||
set(ANDROID_MIN_SDK_VERSION "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android minSdkVersion")
|
||||
else()
|
||||
set(ANDROID_MIN_SDK_VERSION "21" CACHE STRING "Android minSdkVersion")
|
||||
endif()
|
||||
set(ANDROID_TARGET_SDK_VERSION "31" CACHE STRING "Android minSdkVersion")
|
||||
set(ANDROID_TARGET_SDK_VERSION "34" CACHE STRING "Android targetSdkVersion")
|
||||
|
||||
set(ANDROID_BUILD_BASE_DIR "${OpenCV_BINARY_DIR}/opencv_android" CACHE INTERNAL "")
|
||||
set(ANDROID_TMP_INSTALL_BASE_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/install/opencv_android")
|
||||
@@ -35,11 +35,11 @@ include '${ANDROID_ABI}'
|
||||
")
|
||||
|
||||
set(ANDROID_INSTALL_ABI_FILTER "
|
||||
//reset()
|
||||
//include 'armeabi-v7a'
|
||||
//include 'arm64-v8a'
|
||||
//include 'x86'
|
||||
//include 'x86_64'
|
||||
reset()
|
||||
include 'armeabi-v7a'
|
||||
include 'arm64-v8a'
|
||||
include 'x86'
|
||||
include 'x86_64'
|
||||
")
|
||||
if(NOT INSTALL_CREATE_DISTRIB)
|
||||
set(ANDROID_INSTALL_ABI_FILTER "${ANDROID_BUILD_ABI_FILTER}")
|
||||
@@ -54,7 +54,9 @@ set(ANDROID_STRICT_BUILD_CONFIGURATION "true")
|
||||
configure_file("${OpenCV_SOURCE_DIR}/samples/android/build.gradle.in" "${ANDROID_BUILD_BASE_DIR}/build.gradle" @ONLY)
|
||||
|
||||
set(ANDROID_ABI_FILTER "${ANDROID_INSTALL_ABI_FILTER}")
|
||||
set(ANDROID_STRICT_BUILD_CONFIGURATION "false")
|
||||
# CI uses NDK 26d to overcome https://github.com/opencv/opencv/issues/26072
|
||||
# It's ahead of default configuration and we have to force version to get non-controversial parts of the package
|
||||
#set(ANDROID_STRICT_BUILD_CONFIGURATION "false")
|
||||
configure_file("${OpenCV_SOURCE_DIR}/samples/android/build.gradle.in" "${ANDROID_TMP_INSTALL_BASE_DIR}/${ANDROID_INSTALL_SAMPLES_DIR}/build.gradle" @ONLY)
|
||||
install(FILES "${ANDROID_TMP_INSTALL_BASE_DIR}/${ANDROID_INSTALL_SAMPLES_DIR}/build.gradle" DESTINATION "${ANDROID_INSTALL_SAMPLES_DIR}" COMPONENT samples)
|
||||
|
||||
|
||||
@@ -78,6 +78,9 @@
|
||||
/* IJG JPEG codec */
|
||||
#cmakedefine HAVE_JPEG
|
||||
|
||||
/* JPEG XL codec */
|
||||
#cmakedefine HAVE_JPEGXL
|
||||
|
||||
/* GDCM DICOM codec */
|
||||
#cmakedefine HAVE_GDCM
|
||||
|
||||
|
||||
+2
-2
@@ -16,8 +16,8 @@ endif()
|
||||
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
if (DOXYGEN_VERSION VERSION_LESS 1.9.8)
|
||||
message(WARNING "Found doxygen ${DOXYGEN_VERSION}, version 1.9.8 is used for testing, there is "
|
||||
if (DOXYGEN_VERSION VERSION_LESS 1.12)
|
||||
message(WARNING "Found doxygen ${DOXYGEN_VERSION}, version 1.12 is used for testing, there is "
|
||||
"a chance your documentation will look different or have some limitations.")
|
||||
endif()
|
||||
add_custom_target(doxygen)
|
||||
|
||||
+67
-5
@@ -1,9 +1,14 @@
|
||||
# Doxyfile 1.12.0
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = OpenCV
|
||||
PROJECT_NUMBER = @OPENCV_VERSION@
|
||||
PROJECT_BRIEF = "Open Source Computer Vision"
|
||||
PROJECT_LOGO = @CMAKE_CURRENT_SOURCE_DIR@/opencv-logo-small.png
|
||||
#PROJECT_ICON =
|
||||
PROJECT_ICON = @CMAKE_CURRENT_SOURCE_DIR@/opencv.ico
|
||||
OUTPUT_DIRECTORY = @CMAKE_DOXYGEN_OUTPUT_PATH@
|
||||
CREATE_SUBDIRS = YES
|
||||
CREATE_SUBDIRS_LEVEL = 8
|
||||
@@ -25,7 +30,8 @@ ABBREVIATE_BRIEF = "The $name class" \
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH = @CMAKE_SOURCE_DIR@/modules @CMAKE_DOXYGEN_INCLUDE_ROOTS@
|
||||
STRIP_FROM_PATH = @CMAKE_SOURCE_DIR@/modules \
|
||||
@CMAKE_DOXYGEN_INCLUDE_ROOTS@
|
||||
STRIP_FROM_INC_PATH = @CMAKE_DOXYGEN_INCLUDE_ROOTS@
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
@@ -67,6 +73,9 @@ TYPEDEF_HIDES_STRUCT = YES
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
NUM_PROC_THREADS = 1
|
||||
TIMESTAMP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PRIV_VIRTUAL = NO
|
||||
@@ -107,6 +116,10 @@ SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE = @CMAKE_DOXYGEN_LAYOUT@
|
||||
CITE_BIB_FILES = @CMAKE_EXTRA_BIB_FILES@
|
||||
EXTERNAL_TOOL_PATH =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = YES
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
@@ -118,6 +131,9 @@ WARN_AS_ERROR = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LINE_FORMAT = "at line $line of file $file"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = @CMAKE_DOXYGEN_INPUT_LIST@
|
||||
INPUT_ENCODING = UTF-8
|
||||
INPUT_FILE_ENCODING =
|
||||
@@ -136,6 +152,10 @@ FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
FORTRAN_COMMENT_AFTER = 72
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
@@ -149,8 +169,14 @@ CLANG_ASSISTED_PARSING = NO
|
||||
CLANG_ADD_INC_PATHS = YES
|
||||
CLANG_OPTIONS =
|
||||
CLANG_DATABASE_PATH =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
@@ -166,8 +192,8 @@ HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_DYNAMIC_MENUS = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_CODE_FOLDING = YES
|
||||
#HTML_COPY_CLIPBOARD = YES
|
||||
#HTML_PROJECT_COOKIE =
|
||||
HTML_COPY_CLIPBOARD = YES
|
||||
HTML_PROJECT_COOKIE =
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
@@ -197,6 +223,7 @@ DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = NO
|
||||
FULL_SIDEBAR = NO
|
||||
ENUM_VALUES_PER_LINE = 1
|
||||
SHOW_ENUM_VALUES = NO
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = YES
|
||||
OBFUSCATE_EMAILS = YES
|
||||
@@ -216,6 +243,9 @@ SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
@@ -234,31 +264,56 @@ LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_EMOJI_DIRECTORY =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_EXTRA_FILES =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_SUBDIR =
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_PROGRAMLISTING = YES
|
||||
XML_NS_MEMB_FILE_SCOPE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to Sqlite3 output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_SQLITE3 = NO
|
||||
SQLITE3_OUTPUT = sqlite3
|
||||
SQLITE3_RECREATE_DB = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
@@ -307,18 +362,24 @@ PREDEFINED = __cplusplus=1 \
|
||||
CV_DEPRECATED=
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE = @CMAKE_DOXYGEN_OUTPUT_PATH@/html/opencv.tag
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to diagram generator tools
|
||||
#---------------------------------------------------------------------------
|
||||
HIDE_UNDOC_RELATIONS = NO
|
||||
HAVE_DOT = @CMAKECONFIG_HAVE_DOT@
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTPATH =
|
||||
DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
|
||||
DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
|
||||
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = NO
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = NO
|
||||
@@ -338,6 +399,7 @@ DOT_IMAGE_FORMAT = @CMAKECONFIG_DOT_IMAGE_FORMAT@
|
||||
INTERACTIVE_SVG = @CMAKECONFIG_INTERACTIVE_SVG@
|
||||
DOT_PATH = @CMAKECONFIG_DOT_PATH@
|
||||
DOTFILE_DIRS =
|
||||
DIA_PATH =
|
||||
DIAFILE_DIRS =
|
||||
PLANTUML_JAR_PATH =
|
||||
PLANTUML_CFG_FILE =
|
||||
|
||||
+4
-7
@@ -1,21 +1,18 @@
|
||||
<!-- HTML footer for doxygen 1.8.6-->
|
||||
<!-- HTML footer for doxygen 1.12.0-->
|
||||
<!-- start footer part -->
|
||||
<!--BEGIN GENERATE_TREEVIEW-->
|
||||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||||
<ul>
|
||||
$navpath
|
||||
<li class="footer">$generatedby
|
||||
<a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
|
||||
<li class="footer">$generatedby <a href="https://www.doxygen.org/index.html"><img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/></a> $doxygenversion </li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--END GENERATE_TREEVIEW-->
|
||||
<!--BEGIN !GENERATE_TREEVIEW-->
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
$generatedby  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
|
||||
</a> $doxygenversion
|
||||
$generatedby <a href="https://www.doxygen.org/index.html"><img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/></a> $doxygenversion
|
||||
</small></address>
|
||||
</div><!-- doc-content -->
|
||||
<!--END !GENERATE_TREEVIEW-->
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
|
||||
+36
-12
@@ -1,24 +1,42 @@
|
||||
<!-- HTML header for doxygen 1.8.6-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!-- HTML header for doxygen 1.12.0-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="$langISO">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
|
||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||
<link href="$relpath^opencv.ico" rel="shortcut icon" type="image/x-icon" />
|
||||
<!--BEGIN PROJECT_ICON-->
|
||||
<link rel="icon" href="$relpath^$projecticon" type="image/x-icon" />
|
||||
<!--END PROJECT_ICON-->
|
||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN FULL_SIDEBAR-->
|
||||
<script type="text/javascript">var page_layout=1;</script>
|
||||
<!--END FULL_SIDEBAR-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
<script type="text/javascript" src="$relpath^tutorial-utils.js"></script>
|
||||
<!--BEGIN COPY_CLIPBOARD-->
|
||||
<script type="text/javascript" src="$relpath^clipboard.js"></script>
|
||||
<!--END COPY_CLIPBOARD-->
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
$darkmode
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
<body>
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN FULL_SIDEBAR-->
|
||||
<div id="side-nav" class="ui-resizable side-nav-resizable"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
<!--END FULL_SIDEBAR-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
|
||||
<!--BEGIN TITLEAREA-->
|
||||
@@ -26,31 +44,37 @@ $extrastylesheet
|
||||
<!--#include virtual="/google-search.html"-->
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr style="height: 56px;">
|
||||
<tr id="projectrow">
|
||||
<!--BEGIN PROJECT_LOGO-->
|
||||
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
|
||||
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"$logosize/></td>
|
||||
<!--END PROJECT_LOGO-->
|
||||
<!--BEGIN PROJECT_NAME-->
|
||||
<td style="padding-left: 0.5em;">
|
||||
<div id="projectname">$projectname
|
||||
<!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
|
||||
<td id="projectalign">
|
||||
<div id="projectname">$projectname<!--BEGIN PROJECT_NUMBER--><span id="projectnumber"> $projectnumber</span><!--END PROJECT_NUMBER-->
|
||||
</div>
|
||||
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
|
||||
</td>
|
||||
<!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME-->
|
||||
<!--BEGIN PROJECT_BRIEF-->
|
||||
<td style="padding-left: 0.5em;">
|
||||
<td>
|
||||
<div id="projectbrief">$projectbrief</div>
|
||||
</td>
|
||||
<!--END PROJECT_BRIEF-->
|
||||
<!--END !PROJECT_NAME-->
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN SEARCHENGINE-->
|
||||
<td>$searchbox</td>
|
||||
<!--BEGIN !FULL_SIDEBAR-->
|
||||
<td>$searchbox</td>
|
||||
<!--END !FULL_SIDEBAR-->
|
||||
<!--END SEARCHENGINE-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
</tr>
|
||||
<!--BEGIN SEARCHENGINE-->
|
||||
<!--BEGIN FULL_SIDEBAR-->
|
||||
<tr><td colspan="2">$searchbox</td></tr>
|
||||
<!--END FULL_SIDEBAR-->
|
||||
<!--END SEARCHENGINE-->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
+5
-14
@@ -424,20 +424,11 @@
|
||||
publisher = {BMVA Press},
|
||||
url = {https://www.researchgate.net/profile/Robert_Fisher5/publication/2237785_A_Buyer's_Guide_to_Conic_Fitting/links/0fcfd50f59aeded518000000/A-Buyers-Guide-to-Conic-Fitting.pdf}
|
||||
}
|
||||
@article{fitzgibbon1999,
|
||||
abstract = {This work presents a new efficient method for fitting ellipses to scattered data. Previous algorithms either fitted general conics or were computationally expensive. By minimizing the algebraic distance subject to the constraint 4ac-b<sup>2</sup>=1, the new method incorporates the ellipticity constraint into the normalization factor. The proposed method combines several advantages: It is ellipse-specific, so that even bad data will always return an ellipse. It can be solved naturally by a generalized eigensystem. It is extremely robust, efficient, and easy to implement},
|
||||
author = {Fitzgibbon, Andrew and Pilu, Maurizio and Fisher, Robert B.},
|
||||
doi = {10.1109/34.765658},
|
||||
isbn = {0162-8828},
|
||||
issn = {01628828},
|
||||
journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence},
|
||||
number = {5},
|
||||
pages = {476--480},
|
||||
pmid = {708},
|
||||
title = {Direct least square fitting of ellipses},
|
||||
volume = {21},
|
||||
year = {1999},
|
||||
url = {https://pdfs.semanticscholar.org/090d/25f94cb021bdd3400a2f547f989a6a5e07ec.pdf}
|
||||
@inproceedings{oy1998NumericallySD,
|
||||
title = {Numerically Stable Direct Least Squares Fitting of Ellipses},
|
||||
author = {Radim Hal oy and Jan Flusser},
|
||||
year = {1998},
|
||||
url = {https://www.semanticscholar.org/paper/Numerically-Stable-Direct-Least-Squares-Fitting-of-oy-Flusser/9a8607575ba9c6016e9f3db5e52f5ed4d14d5dfd}
|
||||
}
|
||||
@article{Gallego2014ACF,
|
||||
title = {A Compact Formula for the Derivative of a 3-D Rotation in Exponential Coordinates},
|
||||
|
||||
@@ -36,7 +36,8 @@ Now let's create a function, draw which takes the corners in the chessboard (obt
|
||||
**cv.findChessboardCorners()**) and **axis points** to draw a 3D axis.
|
||||
@code{.py}
|
||||
def draw(img, corners, imgpts):
|
||||
corner = tuple(corners[0].ravel())
|
||||
corner = tuple(corners[0].ravel().astype("int32"))
|
||||
imgpts = imgpts.astype("int32")
|
||||
img = cv.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5)
|
||||
img = cv.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5)
|
||||
img = cv.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5)
|
||||
|
||||
+2264
-26
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
Handling Animated Image Files {#tutorial_animations}
|
||||
===========================
|
||||
|
||||
@tableofcontents
|
||||
|
||||
| | |
|
||||
| -: | :- |
|
||||
| Original author | Suleyman Turkmen (with help of ChatGPT) |
|
||||
| Compatibility | OpenCV >= 4.11 |
|
||||
|
||||
Goal
|
||||
----
|
||||
In this tutorial, you will learn how to:
|
||||
|
||||
- Use `cv::imreadanimation` to load frames from animated image files.
|
||||
- Understand the structure and parameters of the `cv::Animation` structure.
|
||||
- Display individual frames from an animation.
|
||||
- Use `cv::imwriteanimation` to write `cv::Animation` to a file.
|
||||
|
||||
Source Code
|
||||
-----------
|
||||
|
||||
@add_toggle_cpp
|
||||
- **Downloadable code**: Click
|
||||
[here](https://github.com/opencv/opencv/tree/4.x/samples/cpp/tutorial_code/imgcodecs/animations.cpp)
|
||||
|
||||
- **Code at a glance:**
|
||||
@include samples/cpp/tutorial_code/imgcodecs/animations.cpp
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
- **Downloadable code**: Click
|
||||
[here](https://github.com/opencv/opencv/tree/4.x/samples/python/tutorial_code/imgcodecs/animations.py)
|
||||
|
||||
- **Code at a glance:**
|
||||
@include samples/python/tutorial_code/imgcodecs/animations.py
|
||||
@end_toggle
|
||||
|
||||
Explanation
|
||||
-----------
|
||||
|
||||
## Initializing the Animation Structure
|
||||
|
||||
Initialize a `cv::Animation` structure to hold the frames from the animated image file.
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet cpp/tutorial_code/imgcodecs/animations.cpp init_animation
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet python/tutorial_code/imgcodecs/animations.py init_animation
|
||||
@end_toggle
|
||||
|
||||
## Loading Frames
|
||||
|
||||
Use `cv::imreadanimation` to load frames from the specified file. Here, we load all frames from an animated WebP image.
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet cpp/tutorial_code/imgcodecs/animations.cpp read_animation
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet python/tutorial_code/imgcodecs/animations.py read_animation
|
||||
@end_toggle
|
||||
|
||||
## Displaying Frames
|
||||
|
||||
Each frame in the `animation.frames` vector can be displayed as a standalone image. This loop iterates through each frame, displaying it in a window with a short delay to simulate the animation.
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet cpp/tutorial_code/imgcodecs/animations.cpp show_animation
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet python/tutorial_code/imgcodecs/animations.py show_animation
|
||||
@end_toggle
|
||||
|
||||
## Saving Animation
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet cpp/tutorial_code/imgcodecs/animations.cpp write_animation
|
||||
@end_toggle
|
||||
|
||||
@add_toggle_python
|
||||
@snippet python/tutorial_code/imgcodecs/animations.py write_animation
|
||||
@end_toggle
|
||||
|
||||
## Summary
|
||||
|
||||
The `cv::imreadanimation` and `cv::imwriteanimation` functions make it easy to work with animated image files by loading frames into a `cv::Animation` structure, allowing frame-by-frame processing.
|
||||
With these functions, you can load, process, and save frames from animated image files like GIF, AVIF, APNG, and WebP.
|
||||
@@ -10,3 +10,4 @@ Application utils (highgui, imgcodecs, videoio modules) {#tutorial_table_of_cont
|
||||
- @subpage tutorial_orbbec_uvc
|
||||
- @subpage tutorial_intelperc
|
||||
- @subpage tutorial_wayland_ubuntu
|
||||
- @subpage tutorial_animations
|
||||
|
||||
@@ -83,7 +83,7 @@ Arranging the terms: \f$r = x \cos \theta + y \sin \theta\f$
|
||||
|
||||
### Standard and Probabilistic Hough Line Transform
|
||||
|
||||
OpenCV implements two kind of Hough Line Transforms:
|
||||
OpenCV implements three kind of Hough Line Transforms:
|
||||
|
||||
a. **The Standard Hough Transform**
|
||||
|
||||
@@ -97,6 +97,12 @@ b. **The Probabilistic Hough Line Transform**
|
||||
of the detected lines \f$(x_{0}, y_{0}, x_{1}, y_{1})\f$
|
||||
- In OpenCV it is implemented with the function **HoughLinesP()**
|
||||
|
||||
c. **The Weighted Hough Transform**
|
||||
|
||||
- Uses edge intensity instead binary 0 or 1 values in standard Hough transform.
|
||||
- In OpenCV it is implemented with the function **HoughLines()** with use_edgeval=true.
|
||||
- See the example in samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp.
|
||||
|
||||
### What does this program do?
|
||||
- Loads an image
|
||||
- Applies a *Standard Hough Line Transform* and a *Probabilistic Line Transform*.
|
||||
|
||||
@@ -310,11 +310,12 @@ Following formats can be read by OpenCV without help of any third-party library:
|
||||
| [JPEG2000 with OpenJPEG](https://en.wikipedia.org/wiki/OpenJPEG) | `WITH_OPENJPEG` | _ON_ | `BUILD_OPENJPEG` |
|
||||
| [JPEG2000 with JasPer](https://en.wikipedia.org/wiki/JasPer) | `WITH_JASPER` | _ON_ (see note) | `BUILD_JASPER` |
|
||||
| [EXR](https://en.wikipedia.org/wiki/OpenEXR) | `WITH_OPENEXR` | _ON_ | `BUILD_OPENEXR` |
|
||||
| [JPEG XL](https://en.wikipedia.org/wiki/JPEG_XL) | `WITH_JPEGXL` | _ON_ | Not supported. (see note) |
|
||||
|
||||
All libraries required to read images in these formats are included into OpenCV and will be built automatically if not found at the configuration stage. Corresponding `BUILD_*` options will force building and using own libraries, they are enabled by default on some platforms, e.g. Windows.
|
||||
|
||||
@note OpenJPEG have higher priority than JasPer which is deprecated. In order to use JasPer, OpenJPEG must be disabled.
|
||||
|
||||
@note (JPEG XL) OpenCV doesn't contain libjxl source code, so `BUILD_JPEGXL` is not supported.
|
||||
|
||||
### GDAL integration
|
||||
|
||||
|
||||
@@ -46,14 +46,14 @@ Open your Doxyfile using your favorite text editor and search for the key
|
||||
`TAGFILES`. Change it as follows:
|
||||
|
||||
@code
|
||||
TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.10.0
|
||||
TAGFILES = ./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.11.0
|
||||
@endcode
|
||||
|
||||
If you had other definitions already, you can append the line using a `\`:
|
||||
|
||||
@code
|
||||
TAGFILES = ./docs/doxygen-tags/libstdc++.tag=https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen \
|
||||
./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.10.0
|
||||
./docs/doxygen-tags/opencv.tag=http://docs.opencv.org/4.11.0
|
||||
@endcode
|
||||
|
||||
Doxygen can now use the information from the tag file to link to the OpenCV
|
||||
|
||||
@@ -9,41 +9,49 @@ Installation in MacOS {#tutorial_macos_install}
|
||||
| Original author | `@sajarindider` |
|
||||
| Compatibility | OpenCV >= 3.4 |
|
||||
|
||||
The following steps have been tested for MacOSX (Mavericks) but should work with other versions as well.
|
||||
The following steps have been tested for macOS (Mavericks) but should work with other versions as well.
|
||||
|
||||
Required Packages
|
||||
-----------------
|
||||
|
||||
- CMake 3.9 or higher
|
||||
- Git
|
||||
- Python 2.7 or later and Numpy 1.5 or later
|
||||
- Python 3.x and NumPy 1.5 or later
|
||||
|
||||
This tutorial will assume you have [Python](https://docs.python.org/3/using/mac.html),
|
||||
[Numpy](https://docs.scipy.org/doc/numpy-1.10.1/user/install.html) and
|
||||
[Git](https://www.atlassian.com/git/tutorials/install-git) installed on your machine.
|
||||
[NumPy](https://numpy.org/install/) and
|
||||
[Git](https://git-scm.com/downloads/mac) installed on your machine.
|
||||
|
||||
@note
|
||||
OSX comes with Python 2.7 by default, you will need to install Python 3.8 if you want to use it specifically.
|
||||
- macOS up to 12.2 (Monterey): Comes with Python 2.7 pre-installed.
|
||||
- macOS 12.3 and later: Python 2.7 has been removed, and no version of Python is included by default.
|
||||
|
||||
It is recommended to install the latest version of Python 3.x (at least Python 3.8) for compatibility with the latest OpenCV Python bindings.
|
||||
|
||||
@note
|
||||
If you XCode and XCode Command Line-Tools installed, you already have git installed on your machine.
|
||||
If you have Xcode and Xcode Command Line Tools installed, Git is already available on your machine.
|
||||
|
||||
Installing CMake
|
||||
----------------
|
||||
-# Find the version for your system and download CMake from their release's [page](https://cmake.org/download/)
|
||||
|
||||
-# Install the dmg package and launch it from Applications. That will give you the UI app of CMake
|
||||
-# Install the `.dmg` package and launch it from Applications. That will give you the UI app of CMake
|
||||
|
||||
-# From the CMake app window, choose menu Tools --> How to Install For Command Line Use. Then, follow the instructions from the pop-up there.
|
||||
|
||||
-# Install folder will be /usr/bin/ by default, submit it by choosing Install command line links.
|
||||
-# The install folder will be `/usr/local/bin/` by default. Complete the installation by choosing Install command line links.
|
||||
|
||||
-# Test that CMake is installed correctly by running:
|
||||
|
||||
-# Test that it works by running
|
||||
@code{.bash}
|
||||
cmake --version
|
||||
@endcode
|
||||
|
||||
@note You can use [Homebrew](https://brew.sh/) to install CMake with @code{.bash} brew install cmake @endcode
|
||||
@note You can use [Homebrew](https://brew.sh/) to install CMake with:
|
||||
|
||||
@code{.bash}
|
||||
brew install cmake
|
||||
@endcode
|
||||
|
||||
Getting OpenCV Source Code
|
||||
--------------------------
|
||||
@@ -53,20 +61,22 @@ You can use the latest stable OpenCV version or you can grab the latest snapshot
|
||||
|
||||
### Getting the Latest Stable OpenCV Version
|
||||
|
||||
- Go to our [downloads page](https://opencv.org/releases).
|
||||
- Download the source archive and unpack it.
|
||||
- Go to our [OpenCV releases page](https://opencv.org/releases).
|
||||
- Download the source archive of the latest version (e.g., OpenCV 4.x) and unpack it.
|
||||
|
||||
### Getting the Cutting-edge OpenCV from the Git Repository
|
||||
|
||||
Launch Git client and clone [OpenCV repository](http://github.com/opencv/opencv).
|
||||
If you need modules from [OpenCV contrib repository](http://github.com/opencv/opencv_contrib) then clone it as well.
|
||||
Launch Git client and clone [OpenCV repository](https://github.com/opencv/opencv).
|
||||
If you need modules from [OpenCV contrib repository](https://github.com/opencv/opencv_contrib) then clone it as well.
|
||||
|
||||
For example:
|
||||
|
||||
@code{.bash}
|
||||
cd ~/<your_working_directory>
|
||||
git clone https://github.com/opencv/opencv.git
|
||||
git clone https://github.com/opencv/opencv_contrib.git
|
||||
@endcode
|
||||
|
||||
For example
|
||||
@code{.bash}
|
||||
cd ~/<my_working_directory>
|
||||
git clone https://github.com/opencv/opencv.git
|
||||
git clone https://github.com/opencv/opencv_contrib.git
|
||||
@endcode
|
||||
Building OpenCV from Source Using CMake
|
||||
---------------------------------------
|
||||
|
||||
@@ -74,53 +84,98 @@ Building OpenCV from Source Using CMake
|
||||
the generated Makefiles, project files as well the object files and output binaries and enter
|
||||
there.
|
||||
|
||||
For example
|
||||
For example:
|
||||
|
||||
@code{.bash}
|
||||
mkdir build_opencv
|
||||
cd build_opencv
|
||||
@endcode
|
||||
|
||||
@note It is good practice to keep clean your source code directories. Create build directory outside of source tree.
|
||||
@note It is good practice to keep your source code directories clean. Create the build directory outside of the source tree.
|
||||
|
||||
-# Configuring. Run `cmake [<some optional parameters>] <path to the OpenCV source directory>`
|
||||
|
||||
For example
|
||||
For example:
|
||||
|
||||
@code{.bash}
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=ON ../opencv
|
||||
@endcode
|
||||
|
||||
or cmake-gui
|
||||
Alternatively, you can use the CMake GUI (`cmake-gui`):
|
||||
|
||||
- set the OpenCV source code path to, e.g. `/home/user/opencv`
|
||||
- set the binary build path to your CMake build directory, e.g. `/home/user/build_opencv`
|
||||
- set the OpenCV source code path to, e.g. `/Users/your_username/opencv`
|
||||
- set the binary build path to your CMake build directory, e.g. `/Users/your_username/build_opencv`
|
||||
- set optional parameters
|
||||
- run: "Configure"
|
||||
- run: "Generate"
|
||||
|
||||
-# Description of some parameters
|
||||
- build type: `CMAKE_BUILD_TYPE=Release` (or `Debug`)
|
||||
- to build with modules from opencv_contrib set `OPENCV_EXTRA_MODULES_PATH` to `<path to
|
||||
opencv_contrib>/modules`
|
||||
- set `BUILD_DOCS=ON` for building documents (doxygen is required)
|
||||
- set `BUILD_EXAMPLES=ON` to build all examples
|
||||
- build type: `-DCMAKE_BUILD_TYPE=Release` (or `Debug`).
|
||||
- include Extra Modules: If you cloned the `opencv_contrib` repository and want to include its modules, set:
|
||||
|
||||
@code{.bash}
|
||||
-DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules
|
||||
@endcode
|
||||
- set `-DBUILD_DOCS=ON` for building documents (doxygen is required)
|
||||
- set `-DBUILD_EXAMPLES=ON` to build all examples
|
||||
|
||||
-# [optional] Building python. Set the following python parameters:
|
||||
- `PYTHON3_EXECUTABLE = <path to python>`
|
||||
- `PYTHON3_INCLUDE_DIR = /usr/include/python<version>`
|
||||
- `PYTHON3_NUMPY_INCLUDE_DIRS =
|
||||
/usr/lib/python<version>/dist-packages/numpy/core/include/`
|
||||
- `-DPYTHON3_EXECUTABLE=$(which python3)`
|
||||
- `-DPYTHON3_INCLUDE_DIR=$(python3 -c "from sysconfig import get_paths as gp; print(gp()['include'])")`
|
||||
- `-DPYTHON3_NUMPY_INCLUDE_DIRS=$(python3 -c "import numpy; print(numpy.get_include())")`
|
||||
@note
|
||||
To specify Python2 versions, you can replace `PYTHON3_` with `PYTHON2_` in the above parameters.
|
||||
Python 2 has reached its end of life. It is recommended to use Python 3 for building Python bindings.
|
||||
|
||||
-# Build. From build directory execute *make*, it is recommended to do this in several threads
|
||||
|
||||
For example
|
||||
For example:
|
||||
|
||||
@code{.bash}
|
||||
make -j7 # runs 7 jobs in parallel
|
||||
make -j$(sysctl -n hw.ncpu) # runs the build using all available CPU cores
|
||||
@endcode
|
||||
|
||||
-# To use OpenCV in your CMake-based projects through `find_package(OpenCV)` specify `OpenCV_DIR=<path_to_build_or_install_directory>` variable.
|
||||
-# After building, you can install OpenCV system-wide using:
|
||||
|
||||
@code{.bash}
|
||||
sudo make install
|
||||
@endcode
|
||||
|
||||
-# To use OpenCV in your CMake-based projects through `find_package(OpenCV)`, specify the `OpenCV_DIR` variable pointing to the build or install directory.
|
||||
|
||||
For example:
|
||||
|
||||
@code{.bash}
|
||||
cmake -DOpenCV_DIR=~/build_opencv ..
|
||||
@endcode
|
||||
|
||||
### Verifying the OpenCV Installation
|
||||
|
||||
After building (and optionally installing) OpenCV, you can verify the installation by checking the version using Python:
|
||||
|
||||
@code{.bash}
|
||||
python3 -c "import cv2; print(cv2.__version__)"
|
||||
@endcode
|
||||
|
||||
This command should output the version of OpenCV you have installed.
|
||||
|
||||
@note
|
||||
You can also use a package manager like [Homebrew](https://brew.sh/)
|
||||
or [pip](https://pip.pypa.io/en/stable/) to install releases of OpenCV only (Not the cutting edge).
|
||||
|
||||
- Installing via Homebrew:
|
||||
|
||||
For example:
|
||||
|
||||
@code{.bash}
|
||||
brew install opencv
|
||||
@endcode
|
||||
|
||||
- Installing via pip:
|
||||
|
||||
For example:
|
||||
|
||||
@code{.bash}
|
||||
pip install opencv-python
|
||||
@endcode
|
||||
|
||||
@note To access the extra modules from `opencv_contrib`, install the `opencv-contrib-python` package using `pip install opencv-contrib-python`.
|
||||
@@ -16,6 +16,7 @@
|
||||
"undistort",
|
||||
"fisheye_initUndistortRectifyMap",
|
||||
"fisheye_projectPoints"
|
||||
]
|
||||
],
|
||||
"UsacParams": ["UsacParams"]
|
||||
}
|
||||
}
|
||||
|
||||
+395
-407
File diff suppressed because it is too large
Load Diff
@@ -589,8 +589,8 @@ void cv::fisheye::initUndistortRectifyMap( InputArray K, InputArray D, InputArra
|
||||
|
||||
if( m1type == CV_16SC2 )
|
||||
{
|
||||
int iu = cv::saturate_cast<int>(u*cv::INTER_TAB_SIZE);
|
||||
int iv = cv::saturate_cast<int>(v*cv::INTER_TAB_SIZE);
|
||||
int iu = cv::saturate_cast<int>(u*static_cast<double>(cv::INTER_TAB_SIZE));
|
||||
int iv = cv::saturate_cast<int>(v*static_cast<double>(cv::INTER_TAB_SIZE));
|
||||
m1[j*2+0] = (short)(iu >> cv::INTER_BITS);
|
||||
m1[j*2+1] = (short)(iv >> cv::INTER_BITS);
|
||||
m2[j] = (ushort)((iv & (cv::INTER_TAB_SIZE-1))*cv::INTER_TAB_SIZE + (iu & (cv::INTER_TAB_SIZE-1)));
|
||||
|
||||
@@ -259,8 +259,8 @@ public:
|
||||
double v = fy*invProj*vecTilt(1) + v0;
|
||||
if( m1type == CV_16SC2 )
|
||||
{
|
||||
int iu = saturate_cast<int>(u*INTER_TAB_SIZE);
|
||||
int iv = saturate_cast<int>(v*INTER_TAB_SIZE);
|
||||
int iu = saturate_cast<int>(u*static_cast<double>(INTER_TAB_SIZE));
|
||||
int iv = saturate_cast<int>(v*static_cast<double>(INTER_TAB_SIZE));
|
||||
m1[j*2] = (short)(iu >> INTER_BITS);
|
||||
m1[j*2+1] = (short)(iv >> INTER_BITS);
|
||||
m2[j] = (ushort)((iv & (INTER_TAB_SIZE-1))*INTER_TAB_SIZE + (iu & (INTER_TAB_SIZE-1)));
|
||||
|
||||
@@ -789,7 +789,7 @@ protected:
|
||||
calcROI = getValidDisparityROI(cROI, cROI, params.mindisp, params.ndisp, params.winSize);
|
||||
|
||||
bm->compute( leftImg, rightImg, tempDisp );
|
||||
tempDisp.convertTo(leftDisp, CV_32F, 1./StereoMatcher::DISP_SCALE);
|
||||
tempDisp.convertTo(leftDisp, CV_32F, 1./static_cast<double>(StereoMatcher::DISP_SCALE));
|
||||
|
||||
//check for fixed-type disparity data type
|
||||
Mat_<float> fixedFloatDisp;
|
||||
@@ -802,7 +802,7 @@ protected:
|
||||
for (int x = 0; x < leftDisp.cols; x++)
|
||||
{
|
||||
if (leftDisp.at<float>(y, x) < params.mindisp)
|
||||
leftDisp.at<float>(y, x) = -1./StereoMatcher::DISP_SCALE; // treat disparity < mindisp as no disparity
|
||||
leftDisp.at<float>(y, x) = -1./static_cast<double>(StereoMatcher::DISP_SCALE); // treat disparity < mindisp as no disparity
|
||||
}
|
||||
|
||||
return params.winSize/2;
|
||||
|
||||
@@ -463,10 +463,6 @@ The function can also be emulated with a matrix expression, for example:
|
||||
*/
|
||||
CV_EXPORTS_W void scaleAdd(InputArray src1, double alpha, InputArray src2, OutputArray dst);
|
||||
|
||||
/** @example samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp
|
||||
Check @ref tutorial_trackbar "the corresponding tutorial" for more details
|
||||
*/
|
||||
|
||||
/** @brief Calculates the weighted sum of two arrays.
|
||||
|
||||
The function addWeighted calculates the weighted sum of two arrays as follows:
|
||||
|
||||
@@ -413,8 +413,9 @@ public:
|
||||
data, which means that no data is copied. This operation is very efficient and can be used to
|
||||
process external data using OpenCV functions. The external data is not automatically deallocated, so
|
||||
you should take care of it.
|
||||
@param step Array of _size.size()-1 steps in case of a multi-dimensional array (the last step is always
|
||||
set to the element size). If not specified, the matrix is assumed to be continuous.
|
||||
@param step Array of _size.size() or _size.size()-1 steps in case of a multi-dimensional array
|
||||
(if specified, the last step must be equal to the element size, otherwise it will be added as such).
|
||||
If not specified, the matrix is assumed to be continuous.
|
||||
*/
|
||||
GpuMatND(SizeArray size, int type, void* data, StepArray step = StepArray());
|
||||
|
||||
|
||||
@@ -79,9 +79,10 @@ It is defined as:
|
||||
@code
|
||||
typedef const _InputArray& InputArray;
|
||||
@endcode
|
||||
where _InputArray is a class that can be constructed from `Mat`, `Mat_<T>`, `Matx<T, m, n>`,
|
||||
`std::vector<T>`, `std::vector<std::vector<T> >`, `std::vector<Mat>`, `std::vector<Mat_<T> >`,
|
||||
`UMat`, `std::vector<UMat>` or `double`. It can also be constructed from a matrix expression.
|
||||
where \ref cv::_InputArray is a class that can be constructed from \ref cv::Mat, \ref cv::Mat_<T>,
|
||||
\ref cv::Matx<T, m, n>, std::vector<T>, std::vector<std::vector<T>>, std::vector<Mat>,
|
||||
std::vector<Mat_<T>>, \ref cv::UMat, std::vector<UMat> or `double`. It can also be constructed from
|
||||
a matrix expression.
|
||||
|
||||
Since this is mostly implementation-level class, and its interface may change in future versions, we
|
||||
do not describe it in details. There are a few key things, though, that should be kept in mind:
|
||||
|
||||
@@ -460,7 +460,7 @@ CV__DEBUG_NS_END
|
||||
|
||||
template<typename _Tp> inline
|
||||
Mat::Mat(const std::vector<_Tp>& vec, bool copyData)
|
||||
: flags(MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()),
|
||||
: flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()),
|
||||
cols(1), data(0), datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
if(vec.empty())
|
||||
@@ -497,7 +497,7 @@ Mat::Mat(const std::initializer_list<int> sizes, const std::initializer_list<_Tp
|
||||
|
||||
template<typename _Tp, std::size_t _Nm> inline
|
||||
Mat::Mat(const std::array<_Tp, _Nm>& arr, bool copyData)
|
||||
: flags(MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)arr.size()),
|
||||
: flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)arr.size()),
|
||||
cols(1), data(0), datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
if(arr.empty())
|
||||
@@ -514,7 +514,7 @@ Mat::Mat(const std::array<_Tp, _Nm>& arr, bool copyData)
|
||||
|
||||
template<typename _Tp, int n> inline
|
||||
Mat::Mat(const Vec<_Tp, n>& vec, bool copyData)
|
||||
: flags(MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows(n), cols(1), data(0),
|
||||
: flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows(n), cols(1), data(0),
|
||||
datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
if( !copyData )
|
||||
@@ -546,7 +546,7 @@ Mat::Mat(const Matx<_Tp,m,n>& M, bool copyData)
|
||||
|
||||
template<typename _Tp> inline
|
||||
Mat::Mat(const Point_<_Tp>& pt, bool copyData)
|
||||
: flags(MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows(2), cols(1), data(0),
|
||||
: flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows(2), cols(1), data(0),
|
||||
datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
if( !copyData )
|
||||
@@ -565,7 +565,7 @@ Mat::Mat(const Point_<_Tp>& pt, bool copyData)
|
||||
|
||||
template<typename _Tp> inline
|
||||
Mat::Mat(const Point3_<_Tp>& pt, bool copyData)
|
||||
: flags(MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows(3), cols(1), data(0),
|
||||
: flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows(3), cols(1), data(0),
|
||||
datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
|
||||
{
|
||||
if( !copyData )
|
||||
@@ -585,7 +585,7 @@ Mat::Mat(const Point3_<_Tp>& pt, bool copyData)
|
||||
|
||||
template<typename _Tp> inline
|
||||
Mat::Mat(const MatCommaInitializer_<_Tp>& commaInitializer)
|
||||
: flags(MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(0), rows(0), cols(0), data(0),
|
||||
: flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(0), rows(0), cols(0), data(0),
|
||||
datastart(0), dataend(0), allocator(0), u(0), size(&rows)
|
||||
{
|
||||
*this = commaInitializer.operator Mat_<_Tp>();
|
||||
@@ -2090,7 +2090,7 @@ SparseMatConstIterator_<_Tp> SparseMat::end() const
|
||||
template<typename _Tp> inline
|
||||
SparseMat_<_Tp>::SparseMat_()
|
||||
{
|
||||
flags = MAGIC_VAL + traits::Type<_Tp>::value;
|
||||
flags = +MAGIC_VAL + traits::Type<_Tp>::value;
|
||||
}
|
||||
|
||||
template<typename _Tp> inline
|
||||
@@ -3248,7 +3248,7 @@ const Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const MatExpr& b)
|
||||
|
||||
template<typename _Tp> inline
|
||||
UMat::UMat(const std::vector<_Tp>& vec, bool copyData)
|
||||
: flags(MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()),
|
||||
: flags(+MAGIC_VAL + traits::Type<_Tp>::value + CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()),
|
||||
cols(1), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows)
|
||||
{
|
||||
if(vec.empty())
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#define OPENCV_VERSION_HPP
|
||||
|
||||
#define CV_VERSION_MAJOR 4
|
||||
#define CV_VERSION_MINOR 10
|
||||
#define CV_VERSION_MINOR 11
|
||||
#define CV_VERSION_REVISION 0
|
||||
#define CV_VERSION_STATUS "-dev"
|
||||
#define CV_VERSION_STATUS ""
|
||||
|
||||
#define CVAUX_STR_EXP(__A) #__A
|
||||
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
|
||||
|
||||
@@ -12,7 +12,8 @@ GpuMatND::~GpuMatND() = default;
|
||||
GpuMatND::GpuMatND(SizeArray _size, int _type, void* _data, StepArray _step) :
|
||||
flags(0), dims(0), data(static_cast<uchar*>(_data)), offset(0)
|
||||
{
|
||||
CV_Assert(_step.empty() || _size.size() == _step.size() + 1);
|
||||
CV_Assert(_step.empty() || _size.size() == _step.size() + 1 ||
|
||||
(_size.size() == _step.size() && _step.back() == (size_t)CV_ELEM_SIZE(_type)));
|
||||
|
||||
setFields(std::move(_size), _type, std::move(_step));
|
||||
}
|
||||
@@ -106,7 +107,8 @@ void GpuMatND::setFields(SizeArray _size, int _type, StepArray _step)
|
||||
else
|
||||
{
|
||||
step = std::move(_step);
|
||||
step.push_back(elemSize());
|
||||
if (step.size() < size.size())
|
||||
step.push_back(elemSize());
|
||||
|
||||
flags = cv::updateContinuityFlag(flags, dims, size.data(), step.data());
|
||||
}
|
||||
|
||||
@@ -2536,8 +2536,7 @@ double dotProd_16s(const short* src1, const short* src2, int len)
|
||||
|
||||
double dotProd_32s(const int* src1, const int* src2, int len)
|
||||
{
|
||||
#if CV_SIMD_64F // TODO: enable for CV_SIMD_SCALABLE_64F
|
||||
// Test failed on RVV(QEMU): Too big difference (=1.20209e-08 > 1.11022e-12)
|
||||
#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F
|
||||
double r = .0;
|
||||
int i = 0;
|
||||
const int step = VTraits<v_int32>::vlanes();
|
||||
|
||||
@@ -171,7 +171,14 @@ void SparseMat::Hdr::clear()
|
||||
hashtab.clear();
|
||||
hashtab.resize(HASH_SIZE0);
|
||||
pool.clear();
|
||||
#if defined(__GNUC__) && (__GNUC__ == 13) && !defined(__clang__) && (__cplusplus >= 202002L)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
#endif
|
||||
pool.resize(nodeSize);
|
||||
#if defined(__GNUC__) && (__GNUC__ == 13) && !defined(__clang__) && (__cplusplus >= 202002L)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
nodeCount = freeList = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,12 +48,16 @@ int normHamming(const uchar* a, int n)
|
||||
# if defined CV_POPCNT_U64
|
||||
for(; i <= n - 8; i += 8)
|
||||
{
|
||||
result += (int)CV_POPCNT_U64(*(uint64*)(a + i));
|
||||
uint64_t val;
|
||||
std::memcpy(&val, a + i, sizeof(val));
|
||||
result += (int)CV_POPCNT_U64(val);
|
||||
}
|
||||
# endif
|
||||
for(; i <= n - 4; i += 4)
|
||||
{
|
||||
result += CV_POPCNT_U32(*(uint*)(a + i));
|
||||
uint32_t val;
|
||||
std::memcpy(&val, a + i, sizeof(val));
|
||||
result += CV_POPCNT_U32(val);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -92,12 +96,18 @@ int normHamming(const uchar* a, const uchar* b, int n)
|
||||
# if defined CV_POPCNT_U64
|
||||
for(; i <= n - 8; i += 8)
|
||||
{
|
||||
result += (int)CV_POPCNT_U64(*(uint64*)(a + i) ^ *(uint64*)(b + i));
|
||||
uint64_t val_a, val_b;
|
||||
std::memcpy(&val_a, a + i, sizeof(val_a));
|
||||
std::memcpy(&val_b, b + i, sizeof(val_b));
|
||||
result += (int)CV_POPCNT_U64(val_a ^ val_b);
|
||||
}
|
||||
# endif
|
||||
for(; i <= n - 4; i += 4)
|
||||
{
|
||||
result += CV_POPCNT_U32(*(uint*)(a + i) ^ *(uint*)(b + i));
|
||||
uint32_t val_a, val_b;
|
||||
std::memcpy(&val_a, a + i, sizeof(val_a));
|
||||
std::memcpy(&val_b, b + i, sizeof(val_b));
|
||||
result += (int)CV_POPCNT_U32(val_a ^ val_b);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1749,18 +1749,22 @@ TEST(Core_Mat_array, copyTo_roi_row)
|
||||
EXPECT_EQ(5, (int)dst2[4]);
|
||||
}
|
||||
|
||||
TEST(Core_Mat_array, SplitMerge)
|
||||
typedef testing::TestWithParam< tuple<int, perf::MatType> > Core_Mat_arrays;
|
||||
|
||||
TEST_P(Core_Mat_arrays, SplitMerge)
|
||||
{
|
||||
std::array<cv::Mat, 3> src;
|
||||
int cn = get<0>(GetParam());
|
||||
int type = get<1>(GetParam());
|
||||
std::vector<cv::Mat> src(cn);
|
||||
for (size_t i = 0; i < src.size(); ++i)
|
||||
{
|
||||
src[i] = Mat(10, 10, CV_8U, Scalar((double)(16 * (i + 1))));
|
||||
src[i] = Mat(10, 10, type, Scalar((double)(16 * (i + 1))));
|
||||
}
|
||||
|
||||
Mat merged;
|
||||
merge(src, merged);
|
||||
|
||||
std::array<cv::Mat, 3> dst;
|
||||
std::vector<cv::Mat> dst(cn);
|
||||
split(merged, dst);
|
||||
|
||||
for (size_t i = 0; i < dst.size(); ++i)
|
||||
@@ -1769,6 +1773,17 @@ TEST(Core_Mat_array, SplitMerge)
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Core_Mat_arrays, testing::Combine(
|
||||
testing::Range(1, 9),
|
||||
testing::Values(
|
||||
perf::MatType(CV_8U),
|
||||
perf::MatType(CV_16U),
|
||||
perf::MatType(CV_32S),
|
||||
perf::MatType(CV_64F)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
TEST(Mat, regression_8680)
|
||||
{
|
||||
Mat_<Point2i> mat(3,1);
|
||||
|
||||
@@ -477,8 +477,9 @@ class Core_DotProductTest : public Core_MatrixTest
|
||||
public:
|
||||
Core_DotProductTest();
|
||||
protected:
|
||||
void run_func();
|
||||
void prepare_to_validation( int test_case_idx );
|
||||
void run_func() CV_OVERRIDE;
|
||||
void prepare_to_validation( int test_case_idx ) CV_OVERRIDE;
|
||||
double get_success_error_level( int test_case_idx, int i, int j ) CV_OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
@@ -498,6 +499,15 @@ void Core_DotProductTest::prepare_to_validation( int )
|
||||
test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = Scalar(cvtest::crossCorr( test_mat[INPUT][0], test_mat[INPUT][1] ));
|
||||
}
|
||||
|
||||
double Core_DotProductTest::get_success_error_level( int test_case_idx, int i, int j )
|
||||
{
|
||||
#ifdef __riscv
|
||||
const int depth = test_mat[i][j].depth();
|
||||
if (depth == CV_64F)
|
||||
return 1.7e-5;
|
||||
#endif
|
||||
return Core_MatrixTest::get_success_error_level( test_case_idx, i, j );
|
||||
}
|
||||
|
||||
///////// crossproduct //////////
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define OPENCV_DNN_VERSION_HPP
|
||||
|
||||
/// Use with major OpenCV version only.
|
||||
#define OPENCV_DNN_API_VERSION 20240521
|
||||
#define OPENCV_DNN_API_VERSION 20241223
|
||||
|
||||
#if !defined CV_DOXYGEN && !defined CV_STATIC_ANALYSIS && !defined CV_DNN_DONT_ADD_INLINE_NS
|
||||
#define CV__DNN_INLINE_NS __CV_CAT(dnn4_v, OPENCV_DNN_API_VERSION)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
// 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.
|
||||
//
|
||||
// Copyright (C) 2017, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
using Utils_blobFromImage = TestBaseWithParam<std::vector<int>>;
|
||||
PERF_TEST_P_(Utils_blobFromImage, HWC_TO_NCHW) {
|
||||
std::vector<int> input_shape = GetParam();
|
||||
|
||||
Mat input(input_shape, CV_32FC3);
|
||||
randu(input, -10.0f, 10.f);
|
||||
|
||||
TEST_CYCLE() {
|
||||
Mat blob = blobFromImage(input);
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Utils_blobFromImage,
|
||||
Values(std::vector<int>{ 32, 32},
|
||||
std::vector<int>{ 64, 64},
|
||||
std::vector<int>{ 128, 128},
|
||||
std::vector<int>{ 256, 256},
|
||||
std::vector<int>{ 512, 512},
|
||||
std::vector<int>{1024, 1024},
|
||||
std::vector<int>{2048, 2048})
|
||||
);
|
||||
|
||||
using Utils_blobFromImages = TestBaseWithParam<std::vector<int>>;
|
||||
PERF_TEST_P_(Utils_blobFromImages, HWC_TO_NCHW) {
|
||||
std::vector<int> input_shape = GetParam();
|
||||
int batch = input_shape.front();
|
||||
std::vector<int> input_shape_no_batch(input_shape.begin()+1, input_shape.end());
|
||||
|
||||
std::vector<Mat> inputs;
|
||||
for (int i = 0; i < batch; i++) {
|
||||
Mat input(input_shape_no_batch, CV_32FC3);
|
||||
randu(input, -10.0f, 10.f);
|
||||
inputs.push_back(input);
|
||||
}
|
||||
|
||||
TEST_CYCLE() {
|
||||
Mat blobs = blobFromImages(inputs);
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Utils_blobFromImages,
|
||||
Values(std::vector<int>{16, 32, 32},
|
||||
std::vector<int>{16, 64, 64},
|
||||
std::vector<int>{16, 128, 128},
|
||||
std::vector<int>{16, 256, 256},
|
||||
std::vector<int>{16, 512, 512},
|
||||
std::vector<int>{16, 1024, 1024},
|
||||
std::vector<int>{16, 2048, 2048})
|
||||
);
|
||||
|
||||
}
|
||||
@@ -126,8 +126,8 @@ public:
|
||||
const google::protobuf::UnknownField& field = unknownFields.field(i);
|
||||
CV_Assert(field.type() == google::protobuf::UnknownField::TYPE_GROUP);
|
||||
CV_CheckGE(field.group().field_count(), 2, "UnknownField should have at least 2 items: name and value");
|
||||
std::string fieldName = field.group().field(0).length_delimited();
|
||||
std::string fieldValue = field.group().field(1).length_delimited();
|
||||
std::string fieldName(field.group().field(0).length_delimited());
|
||||
std::string fieldValue(field.group().field(1).length_delimited());
|
||||
params.set(fieldName, fieldValue);
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,7 @@ public:
|
||||
const Reflection *refl = msg.GetReflection();
|
||||
int type = field->cpp_type();
|
||||
bool isRepeated = field->is_repeated();
|
||||
const std::string &name = field->name();
|
||||
const std::string name(field->name());
|
||||
|
||||
#define SET_UP_FILED(getter, arrayConstr, gtype) \
|
||||
if (isRepeated) { \
|
||||
@@ -189,7 +189,7 @@ public:
|
||||
params.set(name, DictValue::arrayString(buf.begin(), size));
|
||||
}
|
||||
else {
|
||||
params.set(name, refl->GetEnum(msg, field)->name());
|
||||
params.set(name, std::string(refl->GetEnum(msg, field)->name()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -212,7 +212,7 @@ public:
|
||||
{
|
||||
const FieldDescriptor *fd = msgDesc->field(fieldId);
|
||||
|
||||
if (!isInternal && !ends_with_param(fd->name()))
|
||||
if (!isInternal && !ends_with_param(std::string(fd->name())))
|
||||
continue;
|
||||
|
||||
const google::protobuf::UnknownFieldSet& unknownFields = msgRefl->GetUnknownFields(msg);
|
||||
|
||||
+152
-22
@@ -126,6 +126,111 @@ Mat blobFromImagesWithParams(InputArrayOfArrays images, const Image2BlobParams&
|
||||
return blob;
|
||||
}
|
||||
|
||||
template<typename Tinp, typename Tout>
|
||||
void blobFromImagesNCHWImpl(const std::vector<Mat>& images, Mat& blob_, const Image2BlobParams& param)
|
||||
{
|
||||
int w = images[0].cols;
|
||||
int h = images[0].rows;
|
||||
int wh = w * h;
|
||||
int nch = images[0].channels();
|
||||
CV_Assert(nch == 1 || nch == 3 || nch == 4);
|
||||
int sz[] = { (int)images.size(), nch, h, w};
|
||||
blob_.create(4, sz, param.ddepth);
|
||||
|
||||
for (size_t k = 0; k < images.size(); ++k)
|
||||
{
|
||||
CV_Assert(images[k].depth() == images[0].depth());
|
||||
CV_Assert(images[k].channels() == images[0].channels());
|
||||
CV_Assert(images[k].size() == images[0].size());
|
||||
|
||||
Tout* p_blob = blob_.ptr<Tout>() + k * nch * wh;
|
||||
Tout* p_blob_r = p_blob;
|
||||
Tout* p_blob_g = p_blob + wh;
|
||||
Tout* p_blob_b = p_blob + 2 * wh;
|
||||
Tout* p_blob_a = p_blob + 3 * wh;
|
||||
|
||||
if (param.swapRB)
|
||||
std::swap(p_blob_r, p_blob_b);
|
||||
|
||||
for (size_t i = 0; i < h; ++i)
|
||||
{
|
||||
const Tinp* p_img_row = images[k].ptr<Tinp>(i);
|
||||
|
||||
if (nch == 1)
|
||||
{
|
||||
for (size_t j = 0; j < w; ++j)
|
||||
{
|
||||
p_blob[i * w + j] = p_img_row[j];
|
||||
}
|
||||
}
|
||||
else if (nch == 3)
|
||||
{
|
||||
for (size_t j = 0; j < w; ++j)
|
||||
{
|
||||
p_blob_r[i * w + j] = p_img_row[j * 3 ];
|
||||
p_blob_g[i * w + j] = p_img_row[j * 3 + 1];
|
||||
p_blob_b[i * w + j] = p_img_row[j * 3 + 2];
|
||||
}
|
||||
}
|
||||
else // if (nch == 4)
|
||||
{
|
||||
for (size_t j = 0; j < w; ++j)
|
||||
{
|
||||
p_blob_r[i * w + j] = p_img_row[j * 4 ];
|
||||
p_blob_g[i * w + j] = p_img_row[j * 4 + 1];
|
||||
p_blob_b[i * w + j] = p_img_row[j * 4 + 2];
|
||||
p_blob_a[i * w + j] = p_img_row[j * 4 + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (param.mean == Scalar() && param.scalefactor == Scalar::all(1.0))
|
||||
return;
|
||||
CV_CheckTypeEQ(param.ddepth, CV_32F, "Scaling and mean substraction is supported only for CV_32F blob depth");
|
||||
|
||||
for (size_t k = 0; k < images.size(); ++k)
|
||||
{
|
||||
for (size_t ch = 0; ch < nch; ++ch)
|
||||
{
|
||||
float cur_mean = param.mean[ch];
|
||||
float cur_scale = param.scalefactor[ch];
|
||||
Tout* p_blob = blob_.ptr<Tout>() + k * nch * wh + ch * wh;
|
||||
for (size_t i = 0; i < wh; ++i)
|
||||
{
|
||||
p_blob[i] = (p_blob[i] - cur_mean) * cur_scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Tout>
|
||||
void blobFromImagesNCHW(const std::vector<Mat>& images, Mat& blob_, const Image2BlobParams& param)
|
||||
{
|
||||
if (images[0].depth() == CV_8U)
|
||||
blobFromImagesNCHWImpl<uint8_t, Tout>(images, blob_, param);
|
||||
else if (images[0].depth() == CV_8S)
|
||||
blobFromImagesNCHWImpl<int8_t, Tout>(images, blob_, param);
|
||||
else if (images[0].depth() == CV_16U)
|
||||
blobFromImagesNCHWImpl<uint16_t, Tout>(images, blob_, param);
|
||||
else if (images[0].depth() == CV_16S)
|
||||
blobFromImagesNCHWImpl<int16_t, Tout>(images, blob_, param);
|
||||
else if (images[0].depth() == CV_32S)
|
||||
blobFromImagesNCHWImpl<int32_t, Tout>(images, blob_, param);
|
||||
else if (images[0].depth() == CV_32F)
|
||||
blobFromImagesNCHWImpl<float, Tout>(images, blob_, param);
|
||||
else if (images[0].depth() == CV_64F)
|
||||
blobFromImagesNCHWImpl<double, Tout>(images, blob_, param);
|
||||
else
|
||||
CV_Error(Error::BadDepth, "Unsupported input image depth for blobFromImagesNCHW");
|
||||
}
|
||||
|
||||
template<typename Tout>
|
||||
void blobFromImagesNCHW(const std::vector<UMat>& images, UMat& blob_, const Image2BlobParams& param)
|
||||
{
|
||||
CV_Error(Error::StsNotImplemented, "");
|
||||
}
|
||||
|
||||
template<class Tmat>
|
||||
void blobFromImagesWithParamsImpl(InputArrayOfArrays images_, Tmat& blob_, const Image2BlobParams& param)
|
||||
{
|
||||
@@ -154,19 +259,6 @@ void blobFromImagesWithParamsImpl(InputArrayOfArrays images_, Tmat& blob_, const
|
||||
Scalar scalefactor = param.scalefactor;
|
||||
Scalar mean = param.mean;
|
||||
|
||||
if (param.swapRB)
|
||||
{
|
||||
if (nch > 2)
|
||||
{
|
||||
std::swap(mean[0], mean[2]);
|
||||
std::swap(scalefactor[0], scalefactor[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Red/blue color swapping requires at least three image channels.");
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < images.size(); i++)
|
||||
{
|
||||
Size imgSize = images[i].size();
|
||||
@@ -203,18 +295,35 @@ void blobFromImagesWithParamsImpl(InputArrayOfArrays images_, Tmat& blob_, const
|
||||
resize(images[i], images[i], size, 0, 0, INTER_LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
if (images[i].depth() == CV_8U && param.ddepth == CV_32F)
|
||||
images[i].convertTo(images[i], CV_32F);
|
||||
|
||||
subtract(images[i], mean, images[i]);
|
||||
multiply(images[i], scalefactor, images[i]);
|
||||
}
|
||||
|
||||
size_t nimages = images.size();
|
||||
Tmat image0 = images[0];
|
||||
CV_Assert(image0.dims == 2);
|
||||
|
||||
if (std::is_same<Tmat, Mat>::value && param.datalayout == DNN_LAYOUT_NCHW)
|
||||
{
|
||||
// Fast implementation for HWC cv::Mat images -> NCHW cv::Mat blob
|
||||
if (param.ddepth == CV_8U)
|
||||
blobFromImagesNCHW<uint8_t>(images, blob_, param);
|
||||
else
|
||||
blobFromImagesNCHW<float>(images, blob_, param);
|
||||
return;
|
||||
}
|
||||
|
||||
if (param.swapRB)
|
||||
{
|
||||
if (nch > 2)
|
||||
{
|
||||
std::swap(mean[0], mean[2]);
|
||||
std::swap(scalefactor[0], scalefactor[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Red/blue color swapping requires at least three image channels.");
|
||||
}
|
||||
}
|
||||
|
||||
if (param.datalayout == DNN_LAYOUT_NCHW)
|
||||
{
|
||||
if (nch == 3 || nch == 4)
|
||||
@@ -225,7 +334,14 @@ void blobFromImagesWithParamsImpl(InputArrayOfArrays images_, Tmat& blob_, const
|
||||
|
||||
for (size_t i = 0; i < nimages; i++)
|
||||
{
|
||||
const Tmat& image = images[i];
|
||||
Tmat& image = images[i];
|
||||
if (image.depth() == CV_8U && param.ddepth == CV_32F)
|
||||
image.convertTo(image, CV_32F);
|
||||
if (mean != Scalar())
|
||||
subtract(image, mean, image);
|
||||
if (scalefactor != Scalar::all(1.0))
|
||||
multiply(image, scalefactor, image);
|
||||
|
||||
CV_Assert(image.depth() == blob_.depth());
|
||||
nch = image.channels();
|
||||
CV_Assert(image.dims == 2 && (nch == 3 || nch == 4));
|
||||
@@ -250,7 +366,14 @@ void blobFromImagesWithParamsImpl(InputArrayOfArrays images_, Tmat& blob_, const
|
||||
|
||||
for (size_t i = 0; i < nimages; i++)
|
||||
{
|
||||
const Tmat& image = images[i];
|
||||
Tmat& image = images[i];
|
||||
if (image.depth() == CV_8U && param.ddepth == CV_32F)
|
||||
image.convertTo(image, CV_32F);
|
||||
if (mean != Scalar())
|
||||
subtract(image, mean, image);
|
||||
if (scalefactor != Scalar::all(1.0))
|
||||
multiply(image, scalefactor, image);
|
||||
|
||||
CV_Assert(image.depth() == blob_.depth());
|
||||
nch = image.channels();
|
||||
CV_Assert(image.dims == 2 && (nch == 1));
|
||||
@@ -269,7 +392,14 @@ void blobFromImagesWithParamsImpl(InputArrayOfArrays images_, Tmat& blob_, const
|
||||
int subMatType = CV_MAKETYPE(param.ddepth, nch);
|
||||
for (size_t i = 0; i < nimages; i++)
|
||||
{
|
||||
const Tmat& image = images[i];
|
||||
Tmat& image = images[i];
|
||||
if (image.depth() == CV_8U && param.ddepth == CV_32F)
|
||||
image.convertTo(image, CV_32F);
|
||||
if (mean != Scalar())
|
||||
subtract(image, mean, image);
|
||||
if (scalefactor != Scalar::all(1.0))
|
||||
multiply(image, scalefactor, image);
|
||||
|
||||
CV_Assert(image.depth() == blob_.depth());
|
||||
CV_Assert(image.channels() == image0.channels());
|
||||
CV_Assert(image.size() == image0.size());
|
||||
|
||||
@@ -938,6 +938,15 @@ struct GeluFunctor : public BaseFunctor {
|
||||
}
|
||||
#endif // HAVE_DNN_NGRAPH
|
||||
|
||||
#ifdef HAVE_CANN
|
||||
Ptr<BackendNode> initCannOp(const std::string& name,
|
||||
const std::vector<Ptr<BackendWrapper> > &inputs,
|
||||
const std::vector<Ptr<BackendNode> >& nodes)
|
||||
{
|
||||
CV_Error(Error::StsNotImplemented, "");
|
||||
}
|
||||
#endif // HAVE_CANN
|
||||
|
||||
int64 getFLOPSPerElement() const { return 100; }
|
||||
};
|
||||
|
||||
|
||||
@@ -107,3 +107,18 @@ void Net::Impl::initCUDABackend(const std::vector<LayerPin>& blobsToKeep_)
|
||||
CV__DNN_INLINE_NS_END
|
||||
}} // namespace cv::dnn
|
||||
#endif // HAVE_CUDA
|
||||
|
||||
namespace cv { namespace dnn {
|
||||
|
||||
bool haveCUDA()
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
int dev = 0;
|
||||
static bool ret = (cudaGetDevice(&dev) == cudaSuccess);
|
||||
return ret;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
}} // namespace cv::dnn
|
||||
|
||||
@@ -29,13 +29,7 @@ namespace cv { namespace dnn {
|
||||
return id == DNN_TARGET_CUDA_FP16 || id == DNN_TARGET_CUDA;
|
||||
}
|
||||
|
||||
constexpr bool haveCUDA() {
|
||||
#ifdef HAVE_CUDA
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
bool haveCUDA();
|
||||
|
||||
#ifdef HAVE_CUDA
|
||||
namespace cuda4dnn { namespace csl {
|
||||
|
||||
@@ -103,25 +103,6 @@ static const std::map<std::string, OpenVINOModelTestCaseInfo>& getOpenVINOTestMo
|
||||
"intel/age-gender-recognition-retail-0013/FP16/age-gender-recognition-retail-0013",
|
||||
"intel/age-gender-recognition-retail-0013/FP32/age-gender-recognition-retail-0013"
|
||||
}},
|
||||
#endif
|
||||
#if INF_ENGINE_RELEASE >= 2021020000
|
||||
// OMZ: 2020.2
|
||||
{ "face-detection-0105", {
|
||||
"intel/face-detection-0105/FP32/face-detection-0105",
|
||||
"intel/face-detection-0105/FP16/face-detection-0105"
|
||||
}},
|
||||
{ "face-detection-0106", {
|
||||
"intel/face-detection-0106/FP32/face-detection-0106",
|
||||
"intel/face-detection-0106/FP16/face-detection-0106"
|
||||
}},
|
||||
#endif
|
||||
#if INF_ENGINE_RELEASE >= 2021040000
|
||||
// OMZ: 2021.4
|
||||
{ "person-vehicle-bike-detection-2004", {
|
||||
"intel/person-vehicle-bike-detection-2004/FP32/person-vehicle-bike-detection-2004",
|
||||
"intel/person-vehicle-bike-detection-2004/FP16/person-vehicle-bike-detection-2004"
|
||||
//"intel/person-vehicle-bike-detection-2004/FP16-INT8/person-vehicle-bike-detection-2004"
|
||||
}},
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -228,7 +209,12 @@ void runIE(Target target, const std::string& xmlPath, const std::string& binPath
|
||||
for (auto&& it : model->inputs())
|
||||
{
|
||||
auto type = it.get_element_type();
|
||||
auto shape = it.get_shape();
|
||||
auto shape_ = it.get_partial_shape();
|
||||
if (shape_.is_dynamic())
|
||||
{
|
||||
FAIL() << "Model should not have dynamic shapes (" << it.get_any_name() << " => " << shape_ << ")";
|
||||
}
|
||||
auto shape = shape_.to_shape();
|
||||
auto& m = inputsMap[it.get_any_name()];
|
||||
|
||||
auto tensor = ov::Tensor(type, shape);
|
||||
@@ -265,10 +251,10 @@ void runIE(Target target, const std::string& xmlPath, const std::string& binPath
|
||||
for (const auto& it : model->outputs())
|
||||
{
|
||||
auto type = it.get_element_type();
|
||||
auto shape = it.get_shape();
|
||||
auto& m = outputsMap[it.get_any_name()];
|
||||
|
||||
auto tensor = infRequest.get_tensor(it);
|
||||
auto shape = tensor.get_shape();
|
||||
if (type == ov::element::f32)
|
||||
{
|
||||
m.create(std::vector<int>(shape.begin(), shape.end()), CV_32F);
|
||||
@@ -341,22 +327,9 @@ TEST_P(DNNTestOpenVINO, models)
|
||||
if (targetId == DNN_TARGET_MYRIAD && (false
|
||||
|| modelName == "person-detection-retail-0013" // ncDeviceOpen:1013 Failed to find booted device after boot
|
||||
|| modelName == "age-gender-recognition-retail-0013" // ncDeviceOpen:1013 Failed to find booted device after boot
|
||||
|| modelName == "face-detection-0105" // get_element_type() must be called on a node with exactly one output
|
||||
|| modelName == "face-detection-0106" // get_element_type() must be called on a node with exactly one output
|
||||
|| modelName == "person-vehicle-bike-detection-2004" // 2021.4+: ncDeviceOpen:1013 Failed to find booted device after boot
|
||||
)
|
||||
)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
if (targetId == DNN_TARGET_OPENCL && (false
|
||||
|| modelName == "face-detection-0106" // Operation: 2278 of type ExperimentalDetectronPriorGridGenerator(op::v6) is not supported
|
||||
)
|
||||
)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
if (targetId == DNN_TARGET_OPENCL_FP16 && (false
|
||||
|| modelName == "face-detection-0106" // Operation: 2278 of type ExperimentalDetectronPriorGridGenerator(op::v6) is not supported
|
||||
)
|
||||
)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
#if INF_ENGINE_VER_MAJOR_GE(2020020000)
|
||||
@@ -399,14 +372,6 @@ TEST_P(DNNTestOpenVINO, models)
|
||||
if (targetId == DNN_TARGET_CPU && checkHardwareSupport(CV_CPU_AVX_512F))
|
||||
eps = 1e-5;
|
||||
#endif
|
||||
#if INF_ENGINE_VER_MAJOR_GE(2021030000)
|
||||
if (targetId == DNN_TARGET_CPU && modelName == "face-detection-0105")
|
||||
eps = 2e-4;
|
||||
#endif
|
||||
#if INF_ENGINE_VER_MAJOR_GE(2021040000)
|
||||
if (targetId == DNN_TARGET_CPU && modelName == "person-vehicle-bike-detection-2004")
|
||||
eps = 1e-6;
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(ieOutputsMap.size(), cvOutputsMap.size());
|
||||
for (auto& srcIt : ieOutputsMap)
|
||||
|
||||
@@ -2691,7 +2691,7 @@ void yoloPostProcessing(
|
||||
}
|
||||
|
||||
if (model_name == "yolonas"){
|
||||
// outs contains 2 elemets of shape [1, 8400, 80] and [1, 8400, 4]. Concat them to get [1, 8400, 84]
|
||||
// outs contains 2 elemets of shape [1, 8400, nc] and [1, 8400, 4]. Concat them to get [1, 8400, nc+4]
|
||||
Mat concat_out;
|
||||
// squeeze the first dimension
|
||||
outs[0] = outs[0].reshape(1, outs[0].size[1]);
|
||||
@@ -2701,12 +2701,12 @@ void yoloPostProcessing(
|
||||
// remove the second element
|
||||
outs.pop_back();
|
||||
// unsqueeze the first dimension
|
||||
outs[0] = outs[0].reshape(0, std::vector<int>{1, 8400, 84});
|
||||
outs[0] = outs[0].reshape(0, std::vector<int>{1, outs[0].size[0], outs[0].size[1]});
|
||||
}
|
||||
|
||||
// assert if last dim is 85 or 84
|
||||
CV_CheckEQ(outs[0].dims, 3, "Invalid output shape. The shape should be [1, #anchors, 85 or 84]");
|
||||
CV_CheckEQ((outs[0].size[2] == nc + 5 || outs[0].size[2] == 80 + 4), true, "Invalid output shape: ");
|
||||
// assert if last dim is nc+5 or nc+4
|
||||
CV_CheckEQ(outs[0].dims, 3, "Invalid output shape. The shape should be [1, #anchors, nc+5 or nc+4]");
|
||||
CV_CheckEQ((outs[0].size[2] == nc + 5 || outs[0].size[2] == nc + 4), true, "Invalid output shape: ");
|
||||
|
||||
for (auto preds : outs){
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ TEST_P(Test_TFLite, face_landmark)
|
||||
{
|
||||
if (backend == DNN_BACKEND_CUDA && target == DNN_TARGET_CUDA_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16);
|
||||
double l1 = 2e-5, lInf = 2e-4;
|
||||
double l1 = 2.2e-5, lInf = 2e-4;
|
||||
if (target == DNN_TARGET_CPU_FP16 || target == DNN_TARGET_CUDA_FP16 || target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD ||
|
||||
(backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL))
|
||||
{
|
||||
|
||||
@@ -43,9 +43,6 @@
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
const string FEATURES2D_DIR = "features2d";
|
||||
const string IMAGE_FILENAME = "tsukuba.png";
|
||||
|
||||
/****************************************************************************************\
|
||||
* Algorithmic tests for descriptor matchers *
|
||||
\****************************************************************************************/
|
||||
|
||||
@@ -23,7 +23,7 @@ GStreamerMediaAdapter::GStreamerMediaAdapter(const cv::GFrameDesc& frameDesc,
|
||||
{
|
||||
#if GST_VERSION_MINOR >= 10
|
||||
// Check that GstBuffer has mono-view, so we can retrieve only one video-meta
|
||||
GAPI_Assert((gst_buffer_get_flags(m_buffer) & GST_VIDEO_BUFFER_FLAG_MULTIPLE_VIEW) == 0);
|
||||
GAPI_Assert((gst_buffer_get_flags(m_buffer) & static_cast<GstBufferFlags>(GST_VIDEO_BUFFER_FLAG_MULTIPLE_VIEW)) == 0);
|
||||
#endif // GST_VERSION_MINOR >= 10
|
||||
|
||||
GstVideoMeta* videoMeta = gst_buffer_get_video_meta(m_buffer);
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#ifdef HAVE_GSTREAMER
|
||||
#include <gst/app/gstappsink.h>
|
||||
#include <gst/gstbuffer.h>
|
||||
|
||||
@@ -83,6 +83,7 @@ if(WITH_WAYLAND AND HAVE_WAYLAND)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ocv_module_include_directories(${WAYLAND_CLIENT_INCLUDE_DIRS} ${XKBCOMMON_INCLUDE_DIRS})
|
||||
elseif(HAVE_QT)
|
||||
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "QT${QT_VERSION_MAJOR}")
|
||||
add_definitions(-DHAVE_QT)
|
||||
|
||||
@@ -531,16 +531,20 @@ control panel.
|
||||
Clicking the label of each trackbar enables editing the trackbar values manually.
|
||||
|
||||
@param trackbarname Name of the created trackbar.
|
||||
@param winname Name of the window that will be used as a parent of the created trackbar.
|
||||
@param value Optional pointer to an integer variable whose value reflects the position of the
|
||||
slider. Upon creation, the slider position is defined by this variable.
|
||||
@param count Maximal position of the slider. The minimal position is always 0.
|
||||
@param onChange Pointer to the function to be called every time the slider changes position. This
|
||||
function should be prototyped as void Foo(int,void\*); , where the first parameter is the trackbar
|
||||
position and the second parameter is the user data (see the next parameter). If the callback is
|
||||
the NULL pointer, no callbacks are called, but only value is updated.
|
||||
@param userdata User data that is passed as is to the callback. It can be used to handle trackbar
|
||||
events without using global variables.
|
||||
@param winname Name of the window that will contain the trackbar.
|
||||
@param value Pointer to the integer value that will be changed by the trackbar.
|
||||
Pass `nullptr` if the value pointer is not used. In this case, manually handle
|
||||
the trackbar position in the callback function.
|
||||
@param count Maximum position of the trackbar.
|
||||
@param onChange Pointer to the function to be called every time the slider changes position.
|
||||
This function should have the prototype void Foo(int, void\*);, where the first parameter is
|
||||
the trackbar position, and the second parameter is the user data (see the next parameter).
|
||||
If the callback is a nullptr, no callbacks are called, but the trackbar's value will still be
|
||||
updated automatically.
|
||||
@param userdata Optional user data that is passed to the callback.
|
||||
@note If the `value` pointer is `nullptr`, the trackbar position must be manually managed.
|
||||
Call the callback function manually with the desired initial value to avoid runtime warnings.
|
||||
@see \ref tutorial_trackbar
|
||||
*/
|
||||
CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname,
|
||||
int* value, int count,
|
||||
|
||||
@@ -219,7 +219,7 @@ CV_IMPL void cvSetWindowProperty(const char* name, int prop_id, double prop_valu
|
||||
//change between fullscreen or not.
|
||||
case cv::WND_PROP_FULLSCREEN:
|
||||
|
||||
if (prop_value != cv::WINDOW_NORMAL && prop_value != cv::WINDOW_FULLSCREEN) // bad argument
|
||||
if ((int)prop_value != cv::WINDOW_NORMAL && (int)prop_value != cv::WINDOW_FULLSCREEN) // bad argument
|
||||
break;
|
||||
|
||||
#if defined (HAVE_QT)
|
||||
|
||||
@@ -662,14 +662,16 @@ CvRect cvGetWindowRect_COCOA( const char* name )
|
||||
{
|
||||
CV_ERROR( CV_StsNullPtr, "NULL window" );
|
||||
} else {
|
||||
NSRect rect = [window frame];
|
||||
@autoreleasepool {
|
||||
NSRect rect = [window frame];
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6
|
||||
NSPoint pt = [window convertRectToScreen:rect].origin;
|
||||
NSPoint pt = [window convertRectToScreen:rect].origin;
|
||||
#else
|
||||
NSPoint pt = [window convertBaseToScreen:rect.origin];
|
||||
NSPoint pt = [window convertBaseToScreen:rect.origin];
|
||||
#endif
|
||||
NSSize sz = [[[window contentView] image] size];
|
||||
result = cvRect(pt.x, pt.y, sz.width, sz.height);
|
||||
NSSize sz = [[[window contentView] image] size];
|
||||
result = cvRect(pt.x, pt.y, sz.width, sz.height);
|
||||
}
|
||||
}
|
||||
|
||||
__END__;
|
||||
|
||||
@@ -2177,7 +2177,7 @@ public:
|
||||
switch (prop)
|
||||
{
|
||||
case cv::WND_PROP_FULLSCREEN:
|
||||
if (value != cv::WINDOW_NORMAL && value != cv::WINDOW_FULLSCREEN) // bad arg
|
||||
if ((int)value != cv::WINDOW_NORMAL && (int)value != cv::WINDOW_FULLSCREEN) // bad arg
|
||||
break;
|
||||
setModeWindow_(window, value);
|
||||
return true;
|
||||
|
||||
@@ -2158,6 +2158,9 @@ static void showSaveDialog(CvWindow& window)
|
||||
#ifdef HAVE_JPEG
|
||||
"JPEG files (*.jpeg;*.jpg;*.jpe)\0*.jpeg;*.jpg;*.jpe\0"
|
||||
#endif
|
||||
#ifdef HAVE_JPEGXL
|
||||
"JPEG XL files (*.jxl)\0*.jxl\0"
|
||||
#endif
|
||||
#ifdef HAVE_TIFF
|
||||
"TIFF Files (*.tiff;*.tif)\0*.tiff;*.tif\0"
|
||||
#endif
|
||||
@@ -2805,7 +2808,7 @@ public:
|
||||
switch ((WindowPropertyFlags)prop)
|
||||
{
|
||||
case WND_PROP_FULLSCREEN:
|
||||
if (value != WINDOW_NORMAL && value != WINDOW_FULLSCREEN) // bad arg
|
||||
if ((int)value != WINDOW_NORMAL && (int)value != WINDOW_FULLSCREEN) // bad arg
|
||||
break;
|
||||
setModeWindow_(window, (int)value);
|
||||
return true;
|
||||
|
||||
@@ -23,6 +23,11 @@ if(HAVE_JPEG)
|
||||
list(APPEND GRFMT_LIBS ${JPEG_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(HAVE_JPEGXL)
|
||||
ocv_include_directories(${OPENJPEG_INCLUDE_DIRS})
|
||||
list(APPEND GRFMT_LIBS ${OPENJPEG_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(HAVE_WEBP)
|
||||
add_definitions(-DHAVE_WEBP)
|
||||
ocv_include_directories(${WEBP_INCLUDE_DIR})
|
||||
@@ -51,6 +56,12 @@ if(HAVE_TIFF)
|
||||
list(APPEND GRFMT_LIBS ${TIFF_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(HAVE_JPEGXL)
|
||||
ocv_include_directories(${JPEGXL_INCLUDE_DIRS})
|
||||
message(STATUS "JPEGXL_INCLUDE_DIRS: ${JPEGXL_INCLUDE_DIRS}")
|
||||
list(APPEND GRFMT_LIBS ${JPEGXL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(HAVE_OPENJPEG)
|
||||
ocv_include_directories(${OPENJPEG_INCLUDE_DIRS})
|
||||
list(APPEND GRFMT_LIBS ${OPENJPEG_LIBRARIES})
|
||||
@@ -78,7 +89,7 @@ if(HAVE_OPENEXR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(HAVE_PNG OR HAVE_TIFF OR HAVE_OPENEXR OR HAVE_SPNG)
|
||||
if(HAVE_PNG OR HAVE_TIFF OR HAVE_OPENEXR OR HAVE_SPNG OR HAVE_JPEGXL)
|
||||
ocv_include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
list(APPEND GRFMT_LIBS ${ZLIB_LIBRARIES})
|
||||
endif()
|
||||
@@ -88,6 +99,10 @@ if(HAVE_GDAL)
|
||||
list(APPEND GRFMT_LIBS ${GDAL_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(HAVE_IMGCODEC_GIF)
|
||||
add_definitions(-DHAVE_IMGCODEC_GIF)
|
||||
endif()
|
||||
|
||||
if(HAVE_IMGCODEC_HDR)
|
||||
add_definitions(-DHAVE_IMGCODEC_HDR)
|
||||
endif()
|
||||
|
||||
@@ -111,8 +111,18 @@ enum ImwriteFlags {
|
||||
IMWRITE_JPEG2000_COMPRESSION_X1000 = 272,//!< For JPEG2000, use to specify the target compression rate (multiplied by 1000). The value can be from 0 to 1000. Default is 1000.
|
||||
IMWRITE_AVIF_QUALITY = 512,//!< For AVIF, it can be a quality between 0 and 100 (the higher the better). Default is 95.
|
||||
IMWRITE_AVIF_DEPTH = 513,//!< For AVIF, it can be 8, 10 or 12. If >8, it is stored/read as CV_32F. Default is 8.
|
||||
IMWRITE_AVIF_SPEED = 514 //!< For AVIF, it is between 0 (slowest) and (fastest). Default is 9.
|
||||
};
|
||||
IMWRITE_AVIF_SPEED = 514,//!< For AVIF, it is between 0 (slowest) and (fastest). Default is 9.
|
||||
IMWRITE_JPEGXL_QUALITY = 640,//!< For JPEG XL, it can be a quality from 0 to 100 (the higher is the better). Default value is 95. If set, distance parameter is re-calicurated from quality level automatically. This parameter request libjxl v0.10 or later.
|
||||
IMWRITE_JPEGXL_EFFORT = 641,//!< For JPEG XL, encoder effort/speed level without affecting decoding speed; it is between 1 (fastest) and 10 (slowest). Default is 7.
|
||||
IMWRITE_JPEGXL_DISTANCE = 642,//!< For JPEG XL, distance level for lossy compression: target max butteraugli distance, lower = higher quality, 0 = lossless; range: 0 .. 25. Default is 1.
|
||||
IMWRITE_JPEGXL_DECODING_SPEED = 643,//!< For JPEG XL, decoding speed tier for the provided options; minimum is 0 (slowest to decode, best quality/density), and maximum is 4 (fastest to decode, at the cost of some quality/density). Default is 0.
|
||||
IMWRITE_GIF_LOOP = 1024,//!< For GIF, it can be a loop flag from 0 to 65535. Default is 0 - loop forever.
|
||||
IMWRITE_GIF_SPEED = 1025,//!< For GIF, it is between 1 (slowest) and 100 (fastest). Default is 96.
|
||||
IMWRITE_GIF_QUALITY = 1026, //!< For GIF, it can be a quality from 1 to 8. Default is 2. See cv::ImwriteGifCompressionFlags.
|
||||
IMWRITE_GIF_DITHER = 1027, //!< For GIF, it can be a quality from -1(most dither) to 3(no dither). Default is 0.
|
||||
IMWRITE_GIF_TRANSPARENCY = 1028, //!< For GIF, the alpha channel lower than this will be set to transparent. Default is 1.
|
||||
IMWRITE_GIF_COLORTABLE = 1029 //!< For GIF, 0 means global color table is used, 1 means local color table is used. Default is 0.
|
||||
};
|
||||
|
||||
enum ImwriteJPEGSamplingFactorParams {
|
||||
IMWRITE_JPEG_SAMPLING_FACTOR_411 = 0x411111, //!< 4x1,1x1,1x1
|
||||
@@ -216,8 +226,50 @@ enum ImwriteHDRCompressionFlags {
|
||||
IMWRITE_HDR_COMPRESSION_RLE = 1
|
||||
};
|
||||
|
||||
//! Imwrite GIF specific values for IMWRITE_GIF_QUALITY parameter key, if larger than 3, then its related to the size of the color table.
|
||||
enum ImwriteGIFCompressionFlags {
|
||||
IMWRITE_GIF_FAST_NO_DITHER = 1,
|
||||
IMWRITE_GIF_FAST_FLOYD_DITHER = 2,
|
||||
IMWRITE_GIF_COLORTABLE_SIZE_8 = 3,
|
||||
IMWRITE_GIF_COLORTABLE_SIZE_16 = 4,
|
||||
IMWRITE_GIF_COLORTABLE_SIZE_32 = 5,
|
||||
IMWRITE_GIF_COLORTABLE_SIZE_64 = 6,
|
||||
IMWRITE_GIF_COLORTABLE_SIZE_128 = 7,
|
||||
IMWRITE_GIF_COLORTABLE_SIZE_256 = 8
|
||||
};
|
||||
|
||||
//! @} imgcodecs_flags
|
||||
|
||||
/** @brief Represents an animation with multiple frames.
|
||||
The `Animation` struct is designed to store and manage data for animated sequences such as those from animated formats (e.g., GIF, AVIF, APNG, WebP).
|
||||
It provides support for looping, background color settings, frame timing, and frame storage.
|
||||
*/
|
||||
struct CV_EXPORTS_W_SIMPLE Animation
|
||||
{
|
||||
//! Number of times the animation should loop. 0 means infinite looping.
|
||||
CV_PROP_RW int loop_count;
|
||||
//! Background color of the animation in BGRA format.
|
||||
CV_PROP_RW Scalar bgcolor;
|
||||
//! Duration for each frame in milliseconds.
|
||||
CV_PROP_RW std::vector<int> durations;
|
||||
//! Vector of frames, where each Mat represents a single frame.
|
||||
CV_PROP_RW std::vector<Mat> frames;
|
||||
|
||||
/** @brief Constructs an Animation object with optional loop count and background color.
|
||||
|
||||
@param loopCount An integer representing the number of times the animation should loop:
|
||||
- `0` (default) indicates infinite looping, meaning the animation will replay continuously.
|
||||
- Positive values denote finite repeat counts, allowing the animation to play a limited number of times.
|
||||
- If a negative value or a value beyond the maximum of `0xffff` (65535) is provided, it is reset to `0`
|
||||
(infinite looping) to maintain valid bounds.
|
||||
|
||||
@param bgColor A `Scalar` object representing the background color in BGRA format:
|
||||
- Defaults to `Scalar()`, indicating an empty color (usually transparent if supported).
|
||||
- This background color provides a solid fill behind frames that have transparency, ensuring a consistent display appearance.
|
||||
*/
|
||||
Animation(int loopCount = 0, Scalar bgColor = Scalar());
|
||||
};
|
||||
|
||||
/** @brief Loads an image from a file.
|
||||
|
||||
@anchor imread
|
||||
@@ -229,6 +281,7 @@ returns an empty matrix.
|
||||
Currently, the following file formats are supported:
|
||||
|
||||
- Windows bitmaps - \*.bmp, \*.dib (always supported)
|
||||
- GIF files - \*.gif (always supported)
|
||||
- JPEG files - \*.jpeg, \*.jpg, \*.jpe (see the *Note* section)
|
||||
- JPEG 2000 files - \*.jp2 (see the *Note* section)
|
||||
- Portable Network Graphics - \*.png (see the *Note* section)
|
||||
@@ -304,6 +357,38 @@ The function imreadmulti loads a specified range from a multi-page image from th
|
||||
*/
|
||||
CV_EXPORTS_W bool imreadmulti(const String& filename, CV_OUT std::vector<Mat>& mats, int start, int count, int flags = IMREAD_ANYCOLOR);
|
||||
|
||||
/** @example samples/cpp/tutorial_code/imgcodecs/animations.cpp
|
||||
An example to show usage of cv::imreadanimation and cv::imwriteanimation functions.
|
||||
Check @ref tutorial_animations "the corresponding tutorial" for more details
|
||||
*/
|
||||
|
||||
/** @brief Loads frames from an animated image file into an Animation structure.
|
||||
|
||||
The function imreadanimation loads frames from an animated image file (e.g., GIF, AVIF, APNG, WEBP) into the provided Animation struct.
|
||||
|
||||
@param filename A string containing the path to the file.
|
||||
@param animation A reference to an Animation structure where the loaded frames will be stored. It should be initialized before the function is called.
|
||||
@param start The index of the first frame to load. This is optional and defaults to 0.
|
||||
@param count The number of frames to load. This is optional and defaults to 32767.
|
||||
|
||||
@return Returns true if the file was successfully loaded and frames were extracted; returns false otherwise.
|
||||
*/
|
||||
CV_EXPORTS_W bool imreadanimation(const String& filename, CV_OUT Animation& animation, int start = 0, int count = INT16_MAX);
|
||||
|
||||
/** @brief Saves an Animation to a specified file.
|
||||
|
||||
The function imwriteanimation saves the provided Animation data to the specified file in an animated format.
|
||||
Supported formats depend on the implementation and may include formats like GIF, AVIF, APNG, or WEBP.
|
||||
|
||||
@param filename The name of the file where the animation will be saved. The file extension determines the format.
|
||||
@param animation A constant reference to an Animation struct containing the frames and metadata to be saved.
|
||||
@param params Optional format-specific parameters encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ...).
|
||||
These parameters are used to specify additional options for the encoding process. Refer to `cv::ImwriteFlags` for details on possible parameters.
|
||||
|
||||
@return Returns true if the animation was successfully saved; returns false otherwise.
|
||||
*/
|
||||
CV_EXPORTS_W bool imwriteanimation(const String& filename, const Animation& animation, const std::vector<int>& params = std::vector<int>());
|
||||
|
||||
/** @brief Returns the number of images inside the given file
|
||||
|
||||
The function imcount returns the number of pages in a multi-page image (e.g. TIFF), the number of frames in an animation (e.g. AVIF), and 1 otherwise.
|
||||
@@ -326,6 +411,10 @@ can be saved using this function, with these exceptions:
|
||||
- With Radiance HDR encoder, non 64-bit float (CV_64F) images can be saved.
|
||||
- All images will be converted to 32-bit float (CV_32F).
|
||||
- With JPEG 2000 encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved.
|
||||
- With JPEG XL encoder, 8-bit unsigned (CV_8U), 16-bit unsigned (CV_16U) and 32-bit float(CV_32F) images can be saved.
|
||||
- JPEG XL images with an alpha channel can be saved using this function.
|
||||
To do this, create 8-bit (or 16-bit, 32-bit float) 4-channel image BGRA, where the alpha channel goes last.
|
||||
Fully transparent pixels should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535/1.0.
|
||||
- With PAM encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved.
|
||||
- With PNG encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved.
|
||||
- PNG images with an alpha channel can be saved using this function. To do this, create
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include <opencv2/core/utils/configuration.private.hpp>
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "grfmt_avif.hpp"
|
||||
|
||||
@@ -242,6 +243,8 @@ bool AvifDecoder::readData(Mat &img) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_animation.durations.push_back(decoder_->imageTiming.duration * 1000);
|
||||
|
||||
if (decoder_->image->exif.size > 0) {
|
||||
m_exif.parseExif(decoder_->image->exif.data, decoder_->image->exif.size);
|
||||
}
|
||||
@@ -297,16 +300,11 @@ bool AvifEncoder::isFormatSupported(int depth) const {
|
||||
|
||||
bool AvifEncoder::write(const Mat &img, const std::vector<int> ¶ms) {
|
||||
std::vector<Mat> img_vec(1, img);
|
||||
return writeToOutput(img_vec, params);
|
||||
return writemulti(img_vec, params);
|
||||
}
|
||||
|
||||
bool AvifEncoder::writemulti(const std::vector<Mat> &img_vec,
|
||||
const std::vector<int> ¶ms) {
|
||||
return writeToOutput(img_vec, params);
|
||||
}
|
||||
|
||||
bool AvifEncoder::writeToOutput(const std::vector<Mat> &img_vec,
|
||||
const std::vector<int> ¶ms) {
|
||||
bool AvifEncoder::writeanimation(const Animation& animation,
|
||||
const std::vector<int> ¶ms) {
|
||||
int bit_depth = 8;
|
||||
int speed = AVIF_SPEED_FASTEST;
|
||||
for (size_t i = 0; i < params.size(); i += 2) {
|
||||
@@ -340,12 +338,12 @@ bool AvifEncoder::writeToOutput(const std::vector<Mat> &img_vec,
|
||||
#endif
|
||||
encoder_->speed = speed;
|
||||
|
||||
const avifAddImageFlags flag = (img_vec.size() == 1)
|
||||
const avifAddImageFlags flag = (animation.frames.size() == 1)
|
||||
? AVIF_ADD_IMAGE_FLAG_SINGLE
|
||||
: AVIF_ADD_IMAGE_FLAG_NONE;
|
||||
std::vector<AvifImageUniquePtr> images;
|
||||
std::vector<cv::Mat> imgs_scaled;
|
||||
for (const cv::Mat &img : img_vec) {
|
||||
for (const cv::Mat &img : animation.frames) {
|
||||
CV_CheckType(
|
||||
img.type(),
|
||||
(bit_depth == 8 && img.depth() == CV_8U) ||
|
||||
@@ -358,13 +356,15 @@ bool AvifEncoder::writeToOutput(const std::vector<Mat> &img_vec,
|
||||
|
||||
images.emplace_back(ConvertToAvif(img, do_lossless, bit_depth));
|
||||
}
|
||||
for (const AvifImageUniquePtr &image : images) {
|
||||
|
||||
for (size_t i = 0; i < images.size(); i++)
|
||||
{
|
||||
OPENCV_AVIF_CHECK_STATUS(
|
||||
avifEncoderAddImage(encoder_, image.get(), /*durationInTimescale=*/1,
|
||||
flag),
|
||||
avifEncoderAddImage(encoder_, images[i].get(), animation.durations[i], flag),
|
||||
encoder_);
|
||||
}
|
||||
|
||||
encoder_->timescale = 1000;
|
||||
OPENCV_AVIF_CHECK_STATUS(avifEncoderFinish(encoder_, output.get()), encoder_);
|
||||
|
||||
if (m_buf) {
|
||||
|
||||
@@ -41,17 +41,12 @@ class AvifEncoder CV_FINAL : public BaseImageEncoder {
|
||||
~AvifEncoder() CV_OVERRIDE;
|
||||
|
||||
bool isFormatSupported(int depth) const CV_OVERRIDE;
|
||||
|
||||
bool write(const Mat& img, const std::vector<int>& params) CV_OVERRIDE;
|
||||
|
||||
bool writemulti(const std::vector<Mat>& img_vec,
|
||||
const std::vector<int>& params) CV_OVERRIDE;
|
||||
bool writeanimation(const Animation& animation, const std::vector<int>& params) CV_OVERRIDE;
|
||||
|
||||
ImageEncoder newEncoder() const CV_OVERRIDE;
|
||||
|
||||
private:
|
||||
bool writeToOutput(const std::vector<Mat>& img_vec,
|
||||
const std::vector<int>& params);
|
||||
avifEncoder* encoder_;
|
||||
};
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#include "grfmt_base.hpp"
|
||||
#include "bitstrm.hpp"
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -139,7 +140,22 @@ bool BaseImageEncoder::setDestination( std::vector<uchar>& buf )
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BaseImageEncoder::writemulti(const std::vector<Mat>&, const std::vector<int>& )
|
||||
bool BaseImageEncoder::writemulti(const std::vector<Mat>& img_vec, const std::vector<int>& params)
|
||||
{
|
||||
if(img_vec.size() > 1)
|
||||
CV_LOG_INFO(NULL, "Multi page image will be written as animation with 1 second frame duration.");
|
||||
|
||||
Animation animation;
|
||||
animation.frames = img_vec;
|
||||
|
||||
for (size_t i = 0; i < animation.frames.size(); i++)
|
||||
{
|
||||
animation.durations.push_back(1000);
|
||||
}
|
||||
return writeanimation(animation, params);
|
||||
}
|
||||
|
||||
bool BaseImageEncoder::writeanimation(const Animation&, const std::vector<int>& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -133,6 +133,8 @@ public:
|
||||
*/
|
||||
virtual bool checkSignature(const String& signature) const;
|
||||
|
||||
const Animation& animation() const { return m_animation; };
|
||||
|
||||
/**
|
||||
* @brief Create and return a new instance of the derived image decoder.
|
||||
* @return A new ImageDecoder object.
|
||||
@@ -151,6 +153,7 @@ protected:
|
||||
bool m_use_rgb; ///< Flag indicating whether to decode the image in RGB order.
|
||||
ExifReader m_exif; ///< Object for reading EXIF metadata from the image.
|
||||
size_t m_frame_count; ///< Number of frames in the image (for animations and multi-page images).
|
||||
Animation m_animation;
|
||||
};
|
||||
|
||||
|
||||
@@ -215,6 +218,8 @@ public:
|
||||
*/
|
||||
virtual bool writemulti(const std::vector<Mat>& img_vec, const std::vector<int>& params);
|
||||
|
||||
virtual bool writeanimation(const Animation& animation, const std::vector<int>& params);
|
||||
|
||||
/**
|
||||
* @brief Get a description of the image encoder (e.g., the format it supports).
|
||||
* @return A string describing the encoder.
|
||||
|
||||
@@ -208,7 +208,12 @@ bool BmpDecoder::readHeader()
|
||||
// in 32 bit case alpha channel is used - so require CV_8UC4 type
|
||||
m_type = iscolor ? ((m_bpp == 32 && m_rle_code != BMP_RGB) ? CV_8UC4 : CV_8UC3 ) : CV_8UC1;
|
||||
m_origin = m_height > 0 ? ORIGIN_BL : ORIGIN_TL;
|
||||
m_height = std::abs(m_height);
|
||||
if ( m_height == std::numeric_limits<int>::min() ) {
|
||||
// abs(std::numeric_limits<int>::min()) is undefined behavior.
|
||||
result = false;
|
||||
} else {
|
||||
m_height = std::abs(m_height);
|
||||
}
|
||||
|
||||
if( !result )
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,181 @@
|
||||
// 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
|
||||
|
||||
#ifndef OPENCV_GRFMT_GIF_HPP
|
||||
#define OPENCV_GRFMT_GIF_HPP
|
||||
#ifdef HAVE_IMGCODEC_GIF
|
||||
|
||||
#include "grfmt_base.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
enum GifOpMode
|
||||
{
|
||||
GRFMT_GIF_Nothing = 0,
|
||||
GRFMT_GIF_PreviousImage = 1,
|
||||
GRFMT_GIF_Background = 2,
|
||||
GRFMT_GIF_Cover = 3
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// GIF Decoder ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GifDecoder CV_FINAL : public BaseImageDecoder
|
||||
{
|
||||
public:
|
||||
GifDecoder();
|
||||
~GifDecoder() CV_OVERRIDE;
|
||||
|
||||
bool readHeader() CV_OVERRIDE;
|
||||
bool readData(Mat& img) CV_OVERRIDE;
|
||||
bool nextPage() CV_OVERRIDE;
|
||||
void close();
|
||||
|
||||
ImageDecoder newDecoder() const CV_OVERRIDE;
|
||||
|
||||
protected:
|
||||
RLByteStream m_strm;
|
||||
|
||||
int bgColor;
|
||||
int depth;
|
||||
int idx;
|
||||
|
||||
GifOpMode opMode;
|
||||
bool hasTransparentColor;
|
||||
uchar transparentColor;
|
||||
int top, left, width, height;
|
||||
|
||||
bool hasRead;
|
||||
std::vector<uchar> globalColorTable;
|
||||
std::vector<uchar> localColorTable;
|
||||
|
||||
int lzwMinCodeSize;
|
||||
int globalColorTableSize;
|
||||
int localColorTableSize;
|
||||
|
||||
Mat lastImage;
|
||||
std::vector<uchar> imgCodeStream;
|
||||
|
||||
struct lzwNodeD
|
||||
{
|
||||
int length;
|
||||
uchar suffix;
|
||||
std::vector<uchar> prefix;
|
||||
};
|
||||
|
||||
void readExtensions();
|
||||
void code2pixel(Mat& img, int start, int k);
|
||||
bool lzwDecode();
|
||||
bool getFrameCount_();
|
||||
bool skipHeader();
|
||||
};
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// GIF Encoder ////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class GifEncoder CV_FINAL : public BaseImageEncoder {
|
||||
public:
|
||||
GifEncoder();
|
||||
~GifEncoder() CV_OVERRIDE;
|
||||
|
||||
bool isFormatSupported(int depth) const CV_OVERRIDE;
|
||||
|
||||
bool write(const Mat& img, const std::vector<int>& params) CV_OVERRIDE;
|
||||
bool writeanimation(const Animation& animation, const std::vector<int>& params) CV_OVERRIDE;
|
||||
|
||||
ImageEncoder newEncoder() const CV_OVERRIDE;
|
||||
|
||||
private:
|
||||
/** Color Quantization **/
|
||||
class OctreeColorQuant
|
||||
{
|
||||
struct OctreeNode
|
||||
{
|
||||
bool isLeaf;
|
||||
std::shared_ptr<OctreeNode> children[8]{};
|
||||
int level;
|
||||
uchar index;
|
||||
int leaf;
|
||||
int pixelCount;
|
||||
size_t redSum, greenSum, blueSum;
|
||||
|
||||
OctreeNode();
|
||||
};
|
||||
|
||||
std::shared_ptr<OctreeNode> root;
|
||||
std::vector<std::shared_ptr<OctreeNode>> m_nodeList[8];
|
||||
int32_t m_bitLength;
|
||||
int32_t m_maxColors;
|
||||
int32_t m_leafCount;
|
||||
uchar m_criticalTransparency;
|
||||
uchar r, g, b; // color under transparent color
|
||||
|
||||
public:
|
||||
explicit OctreeColorQuant(int maxColors = 256, int bitLength = 8, uchar criticalTransparency = 1);
|
||||
|
||||
int getPalette(uchar* colorTable);
|
||||
uchar getLeaf(uchar red, uchar green, uchar blue);
|
||||
|
||||
void addMat(const Mat& img);
|
||||
void addMats(const std::vector<Mat>& img_vec);
|
||||
void addColor(int red, int green, int blue);
|
||||
void reduceTree();
|
||||
void recurseReduce(const std::shared_ptr<OctreeNode>& node);
|
||||
};
|
||||
|
||||
enum GifDithering // normal dithering level is -1 to 2
|
||||
{
|
||||
GRFMT_GIF_None = 3,
|
||||
GRFMT_GIF_FloydSteinberg = 4
|
||||
};
|
||||
|
||||
WLByteStream strm;
|
||||
int m_width, m_height;
|
||||
|
||||
int globalColorTableSize;
|
||||
int localColorTableSize;
|
||||
|
||||
uchar opMode;
|
||||
uchar criticalTransparency;
|
||||
uchar transparentColor;
|
||||
Vec3b transparentRGB;
|
||||
int top, left, width, height;
|
||||
|
||||
OctreeColorQuant quantG;
|
||||
OctreeColorQuant quantL;
|
||||
|
||||
std::vector<int16_t> lzwTable;
|
||||
std::vector<uchar> imgCodeStream;
|
||||
|
||||
std::vector<uchar> globalColorTable;
|
||||
std::vector<uchar> localColorTable;
|
||||
|
||||
// params
|
||||
int loopCount;
|
||||
int frameDelay;
|
||||
int colorNum;
|
||||
int bitDepth;
|
||||
int dithering;
|
||||
int lzwMinCodeSize, lzwMaxCodeSize;
|
||||
bool fast;
|
||||
|
||||
bool writeFrames(const std::vector<Mat>& img_vec, const std::vector<int>& params);
|
||||
bool writeHeader(const std::vector<Mat>& img_vec);
|
||||
bool writeFrame(const Mat& img);
|
||||
bool pixel2code(const Mat& img);
|
||||
void getColorTable(const std::vector<Mat>& img_vec, bool isGlobal);
|
||||
static int ditheringKernel(const Mat &img, Mat &img_, int depth, uchar transparency);
|
||||
bool lzwEncode();
|
||||
void close();
|
||||
};
|
||||
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // HAVE_IMGCODEC_GIF
|
||||
#endif //OPENCV_GRFMT_GIF_HPP
|
||||
@@ -0,0 +1,420 @@
|
||||
// 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 "grfmt_jpegxl.hpp"
|
||||
|
||||
#ifdef HAVE_JPEGXL
|
||||
|
||||
#include <jxl/encode_cxx.h>
|
||||
#include <jxl/version.h>
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
/////////////////////// JpegXLDecoder ///////////////////
|
||||
|
||||
JpegXLDecoder::JpegXLDecoder() : m_f(nullptr, &fclose)
|
||||
{
|
||||
m_signature = "\xFF\x0A";
|
||||
m_decoder = nullptr;
|
||||
m_buf_supported = false;
|
||||
m_type = m_convert = -1;
|
||||
m_status = JXL_DEC_NEED_MORE_INPUT;
|
||||
}
|
||||
|
||||
JpegXLDecoder::~JpegXLDecoder()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void JpegXLDecoder::close()
|
||||
{
|
||||
if (m_decoder)
|
||||
m_decoder.release();
|
||||
if (m_f)
|
||||
m_f.release();
|
||||
m_read_buffer = {};
|
||||
m_width = m_height = 0;
|
||||
m_type = m_convert = -1;
|
||||
m_status = JXL_DEC_NEED_MORE_INPUT;
|
||||
}
|
||||
|
||||
// see https://github.com/libjxl/libjxl/blob/v0.10.0/doc/format_overview.md
|
||||
size_t JpegXLDecoder::signatureLength() const
|
||||
{
|
||||
return 12; // For an ISOBMFF-based container
|
||||
}
|
||||
|
||||
bool JpegXLDecoder::checkSignature( const String& signature ) const
|
||||
{
|
||||
// A "naked" codestream.
|
||||
if (
|
||||
( signature.size() >= 2 ) &&
|
||||
( memcmp( signature.c_str(), "\xFF\x0A", 2 ) == 0 )
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// An ISOBMFF-based container.
|
||||
// 0x0000_000C_4A58_4C20_0D0A_870A.
|
||||
if (
|
||||
( signature.size() >= 12 ) &&
|
||||
( memcmp( signature.c_str(), "\x00\x00\x00\x0C\x4A\x58\x4C\x20\x0D\x0A\x87\x0A", 12 ) == 0 )
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageDecoder JpegXLDecoder::newDecoder() const
|
||||
{
|
||||
return makePtr<JpegXLDecoder>();
|
||||
}
|
||||
|
||||
bool JpegXLDecoder::read(Mat* pimg)
|
||||
{
|
||||
// Open file
|
||||
if (!m_f) {
|
||||
m_f.reset(fopen(m_filename.c_str(), "rb"));
|
||||
if (!m_f)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize decoder
|
||||
if (!m_decoder) {
|
||||
m_decoder = JxlDecoderMake(nullptr);
|
||||
if (!m_decoder)
|
||||
return false;
|
||||
// Subscribe to the basic info event
|
||||
JxlDecoderStatus status = JxlDecoderSubscribeEvents(m_decoder.get(), JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE);
|
||||
if (status != JXL_DEC_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up parallel m_parallel_runner
|
||||
if (!m_parallel_runner) {
|
||||
m_parallel_runner = JxlThreadParallelRunnerMake(nullptr, cv::getNumThreads());
|
||||
if (JXL_DEC_SUCCESS != JxlDecoderSetParallelRunner(m_decoder.get(),
|
||||
JxlThreadParallelRunner,
|
||||
m_parallel_runner.get())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create buffer for reading
|
||||
const size_t read_buffer_size = 16384; // 16KB chunks
|
||||
if (m_read_buffer.capacity() < read_buffer_size)
|
||||
m_read_buffer.resize(read_buffer_size);
|
||||
|
||||
// Create image if needed
|
||||
if (m_type != -1 && pimg) {
|
||||
pimg->create(m_height, m_width, m_type);
|
||||
if (!pimg->isContinuous())
|
||||
return false;
|
||||
if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer(m_decoder.get(),
|
||||
&m_format,
|
||||
pimg->ptr<uint8_t>(),
|
||||
pimg->total() * pimg->elemSize())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Start decoding loop
|
||||
do {
|
||||
// Check if we need more input
|
||||
if (m_status == JXL_DEC_NEED_MORE_INPUT) {
|
||||
size_t remaining = JxlDecoderReleaseInput(m_decoder.get());
|
||||
// Move any remaining bytes to the beginning
|
||||
if (remaining > 0)
|
||||
memmove(m_read_buffer.data(), m_read_buffer.data() + m_read_buffer.size() - remaining, remaining);
|
||||
// Read more data from file
|
||||
size_t bytes_read = fread(m_read_buffer.data() + remaining,
|
||||
1, m_read_buffer.size() - remaining, m_f.get());
|
||||
if (bytes_read == 0) {
|
||||
if (ferror(m_f.get())) {
|
||||
CV_LOG_WARNING(NULL, "Error reading input file");
|
||||
return false;
|
||||
}
|
||||
// If we reached EOF but decoder needs more input, file is truncated
|
||||
if (m_status == JXL_DEC_NEED_MORE_INPUT) {
|
||||
CV_LOG_WARNING(NULL, "Truncated JXL file");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Set input buffer
|
||||
if (JXL_DEC_SUCCESS != JxlDecoderSetInput(m_decoder.get(),
|
||||
m_read_buffer.data(),
|
||||
bytes_read + remaining)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the next decoder status
|
||||
m_status = JxlDecoderProcessInput(m_decoder.get());
|
||||
|
||||
// Handle different decoder states
|
||||
switch (m_status) {
|
||||
case JXL_DEC_BASIC_INFO: {
|
||||
if (m_type != -1)
|
||||
return false;
|
||||
JxlBasicInfo info;
|
||||
if (JXL_DEC_SUCCESS != JxlDecoderGetBasicInfo(m_decoder.get(), &info))
|
||||
return false;
|
||||
|
||||
// total channels (Color + Alpha)
|
||||
const uint32_t ncn = info.num_color_channels + info.num_extra_channels;
|
||||
|
||||
m_width = info.xsize;
|
||||
m_height = info.ysize;
|
||||
m_format = {
|
||||
ncn,
|
||||
JXL_TYPE_UINT8, // (temporary)
|
||||
JXL_LITTLE_ENDIAN, // endianness
|
||||
0 // align stride to bytes
|
||||
};
|
||||
if (!m_use_rgb) {
|
||||
switch (ncn) {
|
||||
case 3:
|
||||
m_convert = cv::COLOR_RGB2BGR;
|
||||
break;
|
||||
case 4:
|
||||
m_convert = cv::COLOR_RGBA2BGRA;
|
||||
break;
|
||||
default:
|
||||
m_convert = -1;
|
||||
}
|
||||
}
|
||||
if (info.exponent_bits_per_sample > 0) {
|
||||
m_format.data_type = JXL_TYPE_FLOAT;
|
||||
m_type = CV_MAKETYPE( CV_32F, ncn );
|
||||
} else {
|
||||
switch (info.bits_per_sample) {
|
||||
case 8:
|
||||
m_format.data_type = JXL_TYPE_UINT8;
|
||||
m_type = CV_MAKETYPE( CV_8U, ncn );
|
||||
break;
|
||||
case 16:
|
||||
m_format.data_type = JXL_TYPE_UINT16;
|
||||
m_type = CV_MAKETYPE( CV_16U, ncn );
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!pimg)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
case JXL_DEC_FULL_IMAGE: {
|
||||
// Image is ready
|
||||
if (m_convert != -1)
|
||||
cv::cvtColor(*pimg, *pimg, m_convert);
|
||||
break;
|
||||
}
|
||||
case JXL_DEC_ERROR: {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (m_status != JXL_DEC_SUCCESS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JpegXLDecoder::readHeader()
|
||||
{
|
||||
close();
|
||||
return read(nullptr);
|
||||
}
|
||||
|
||||
bool JpegXLDecoder::readData(Mat& img)
|
||||
{
|
||||
if (!m_decoder || m_width == 0 || m_height == 0)
|
||||
return false;
|
||||
return read(&img);
|
||||
}
|
||||
|
||||
/////////////////////// JpegXLEncoder ///////////////////
|
||||
|
||||
JpegXLEncoder::JpegXLEncoder()
|
||||
{
|
||||
m_description = "JPEG XL files (*.jxl)";
|
||||
m_buf_supported = true;
|
||||
}
|
||||
|
||||
JpegXLEncoder::~JpegXLEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
ImageEncoder JpegXLEncoder::newEncoder() const
|
||||
{
|
||||
return makePtr<JpegXLEncoder>();
|
||||
}
|
||||
|
||||
bool JpegXLEncoder::isFormatSupported( int depth ) const
|
||||
{
|
||||
return depth == CV_8U || depth == CV_16U || depth == CV_32F;
|
||||
}
|
||||
|
||||
bool JpegXLEncoder::write(const Mat& img, const std::vector<int>& params)
|
||||
{
|
||||
m_last_error.clear();
|
||||
|
||||
JxlEncoderPtr encoder = JxlEncoderMake(nullptr);
|
||||
if (!encoder)
|
||||
return false;
|
||||
|
||||
JxlThreadParallelRunnerPtr runner = JxlThreadParallelRunnerMake(
|
||||
/*memory_manager=*/nullptr, cv::getNumThreads());
|
||||
if (JXL_ENC_SUCCESS != JxlEncoderSetParallelRunner(encoder.get(), JxlThreadParallelRunner, runner.get()))
|
||||
return false;
|
||||
|
||||
CV_CheckDepth(img.depth(),
|
||||
( img.depth() == CV_8U || img.depth() == CV_16U || img.depth() == CV_32F ),
|
||||
"JPEG XL encoder only supports CV_8U, CV_16U, CV_32F");
|
||||
CV_CheckChannels(img.channels(),
|
||||
( img.channels() == 1 || img.channels() == 3 || img.channels() == 4) ,
|
||||
"JPEG XL encoder only supports 1, 3, 4 channels");
|
||||
|
||||
WLByteStream strm;
|
||||
if( m_buf ) {
|
||||
if( !strm.open( *m_buf ) )
|
||||
return false;
|
||||
}
|
||||
else if( !strm.open( m_filename )) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JxlBasicInfo info;
|
||||
JxlEncoderInitBasicInfo(&info);
|
||||
info.xsize = img.cols;
|
||||
info.ysize = img.rows;
|
||||
info.uses_original_profile = JXL_FALSE;
|
||||
|
||||
if( img.channels() == 4 )
|
||||
{
|
||||
info.num_color_channels = 3;
|
||||
info.num_extra_channels = 1;
|
||||
|
||||
info.bits_per_sample =
|
||||
info.alpha_bits = 8 * static_cast<int>(img.elemSize1());
|
||||
|
||||
info.exponent_bits_per_sample =
|
||||
info.alpha_exponent_bits = img.depth() == CV_32F ? 8 : 0;
|
||||
}else{
|
||||
info.num_color_channels = img.channels();
|
||||
info.bits_per_sample = 8 * static_cast<int>(img.elemSize1());
|
||||
info.exponent_bits_per_sample = img.depth() == CV_32F ? 8 : 0;
|
||||
}
|
||||
|
||||
if (JxlEncoderSetBasicInfo(encoder.get(), &info) != JXL_ENC_SUCCESS)
|
||||
return false;
|
||||
|
||||
JxlDataType type = JXL_TYPE_UINT8;
|
||||
if (img.depth() == CV_32F)
|
||||
type = JXL_TYPE_FLOAT;
|
||||
else if (img.depth() == CV_16U)
|
||||
type = JXL_TYPE_UINT16;
|
||||
JxlPixelFormat format = {(uint32_t)img.channels(), type, JXL_NATIVE_ENDIAN, 0};
|
||||
JxlColorEncoding color_encoding = {};
|
||||
JXL_BOOL is_gray(format.num_channels < 3 ? JXL_TRUE : JXL_FALSE);
|
||||
JxlColorEncodingSetToSRGB(&color_encoding, is_gray);
|
||||
if (JXL_ENC_SUCCESS != JxlEncoderSetColorEncoding(encoder.get(), &color_encoding))
|
||||
return false;
|
||||
|
||||
Mat image;
|
||||
switch ( img.channels() ) {
|
||||
case 3:
|
||||
cv::cvtColor(img, image, cv::COLOR_BGR2RGB);
|
||||
break;
|
||||
case 4:
|
||||
cv::cvtColor(img, image, cv::COLOR_BGRA2RGBA);
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
if(img.isContinuous()) {
|
||||
image = img;
|
||||
} else {
|
||||
image = img.clone(); // reconstruction as continuous image.
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!image.isContinuous())
|
||||
return false;
|
||||
|
||||
JxlEncoderFrameSettings* frame_settings = JxlEncoderFrameSettingsCreate(encoder.get(), nullptr);
|
||||
// set frame settings from params if available
|
||||
for( size_t i = 0; i < params.size(); i += 2 )
|
||||
{
|
||||
if( params[i] == IMWRITE_JPEGXL_QUALITY )
|
||||
{
|
||||
#if JPEGXL_MAJOR_VERSION > 0 || JPEGXL_MINOR_VERSION >= 10
|
||||
int quality = params[i+1];
|
||||
quality = MIN(MAX(quality, 0), 100);
|
||||
const float distance = JxlEncoderDistanceFromQuality(static_cast<float>(quality));
|
||||
JxlEncoderSetFrameDistance(frame_settings, distance);
|
||||
if (distance == 0)
|
||||
JxlEncoderSetFrameLossless(frame_settings, JXL_TRUE);
|
||||
#else
|
||||
CV_LOG_ONCE_WARNING(NULL, "Quality parameter is supported with libjxl v0.10.0 or later");
|
||||
#endif
|
||||
}
|
||||
if( params[i] == IMWRITE_JPEGXL_DISTANCE )
|
||||
{
|
||||
int distance = params[i+1];
|
||||
distance = MIN(MAX(distance, 0), 25);
|
||||
JxlEncoderSetFrameDistance(frame_settings, distance);
|
||||
if (distance == 0)
|
||||
JxlEncoderSetFrameLossless(frame_settings, JXL_TRUE);
|
||||
}
|
||||
if( params[i] == IMWRITE_JPEGXL_EFFORT )
|
||||
{
|
||||
int effort = params[i+1];
|
||||
effort = MIN(MAX(effort, 1), 10);
|
||||
JxlEncoderFrameSettingsSetOption(frame_settings, JXL_ENC_FRAME_SETTING_EFFORT, effort);
|
||||
}
|
||||
if( params[i] == IMWRITE_JPEGXL_DECODING_SPEED )
|
||||
{
|
||||
int speed = params[i+1];
|
||||
speed = MIN(MAX(speed, 0), 4);
|
||||
JxlEncoderFrameSettingsSetOption(frame_settings, JXL_ENC_FRAME_SETTING_DECODING_SPEED, speed);
|
||||
}
|
||||
}
|
||||
if (JXL_ENC_SUCCESS !=
|
||||
JxlEncoderAddImageFrame(frame_settings, &format,
|
||||
static_cast<const void*>(image.ptr<uint8_t>()),
|
||||
image.total() * image.elemSize())) {
|
||||
return false;
|
||||
}
|
||||
JxlEncoderCloseInput(encoder.get());
|
||||
|
||||
const size_t buffer_size = 16384; // 16KB chunks
|
||||
|
||||
std::vector<uint8_t> compressed(buffer_size);
|
||||
JxlEncoderStatus process_result = JXL_ENC_NEED_MORE_OUTPUT;
|
||||
while (process_result == JXL_ENC_NEED_MORE_OUTPUT) {
|
||||
uint8_t* next_out = compressed.data();
|
||||
size_t avail_out = buffer_size;
|
||||
process_result = JxlEncoderProcessOutput(encoder.get(), &next_out, &avail_out);
|
||||
if (JXL_ENC_ERROR == process_result)
|
||||
return false;
|
||||
const size_t write_size = buffer_size - avail_out;
|
||||
if ( strm.putBytes(compressed.data(), write_size) == false )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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.
|
||||
#ifndef _GRFMT_JPEGXL_H_
|
||||
#define _GRFMT_JPEGXL_H_
|
||||
|
||||
#ifdef HAVE_JPEGXL
|
||||
|
||||
#include "grfmt_base.hpp"
|
||||
#include <jxl/decode_cxx.h>
|
||||
#include <jxl/thread_parallel_runner_cxx.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
// Jpeg XL codec
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief JpegXL codec using libjxl library
|
||||
*/
|
||||
|
||||
class JpegXLDecoder CV_FINAL : public BaseImageDecoder
|
||||
{
|
||||
public:
|
||||
|
||||
JpegXLDecoder();
|
||||
virtual ~JpegXLDecoder();
|
||||
|
||||
bool readData( Mat& img ) CV_OVERRIDE;
|
||||
bool readHeader() CV_OVERRIDE;
|
||||
void close();
|
||||
size_t signatureLength() const CV_OVERRIDE;
|
||||
bool checkSignature( const String& signature ) const CV_OVERRIDE;
|
||||
|
||||
ImageDecoder newDecoder() const CV_OVERRIDE;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<FILE, int (*)(FILE*)> m_f;
|
||||
JxlDecoderPtr m_decoder;
|
||||
JxlThreadParallelRunnerPtr m_parallel_runner;
|
||||
JxlPixelFormat m_format;
|
||||
int m_convert;
|
||||
std::vector<uint8_t> m_read_buffer;
|
||||
JxlDecoderStatus m_status;
|
||||
|
||||
private:
|
||||
bool read(Mat* pimg);
|
||||
};
|
||||
|
||||
|
||||
class JpegXLEncoder CV_FINAL : public BaseImageEncoder
|
||||
{
|
||||
public:
|
||||
JpegXLEncoder();
|
||||
virtual ~JpegXLEncoder();
|
||||
|
||||
bool isFormatSupported( int depth ) const CV_OVERRIDE;
|
||||
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
|
||||
ImageEncoder newEncoder() const CV_OVERRIDE;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif/*_GRFMT_JPEGXL_H_*/
|
||||
+1324
-94
File diff suppressed because it is too large
Load Diff
@@ -47,34 +47,161 @@
|
||||
|
||||
#include "grfmt_base.hpp"
|
||||
#include "bitstrm.hpp"
|
||||
#include <png.h>
|
||||
#include <zlib.h>
|
||||
#include <vector>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
struct Chunk { std::vector<unsigned char> p; };
|
||||
struct OP { unsigned char* p; uint32_t size; int x, y, w, h, valid, filters; };
|
||||
|
||||
typedef struct {
|
||||
unsigned char r, g, b;
|
||||
} rgb;
|
||||
|
||||
class APNGFrame {
|
||||
public:
|
||||
|
||||
APNGFrame();
|
||||
|
||||
// Destructor
|
||||
~APNGFrame();
|
||||
|
||||
bool setMat(const cv::Mat& src, unsigned delayNum = 1, unsigned delayDen = 1000);
|
||||
|
||||
// Getters and Setters
|
||||
unsigned char* getPixels() const { return _pixels; }
|
||||
void setPixels(unsigned char* pixels);
|
||||
|
||||
unsigned int getWidth() const { return _width; }
|
||||
void setWidth(unsigned int width);
|
||||
|
||||
unsigned int getHeight() const { return _height; }
|
||||
void setHeight(unsigned int height);
|
||||
|
||||
unsigned char getColorType() const { return _colorType; }
|
||||
void setColorType(unsigned char colorType);
|
||||
|
||||
rgb* getPalette() { return _palette; }
|
||||
void setPalette(const rgb* palette);
|
||||
|
||||
unsigned char* getTransparency() { return _transparency; }
|
||||
void setTransparency(const unsigned char* transparency);
|
||||
|
||||
int getPaletteSize() const { return _paletteSize; }
|
||||
void setPaletteSize(int paletteSize);
|
||||
|
||||
int getTransparencySize() const { return _transparencySize; }
|
||||
void setTransparencySize(int transparencySize);
|
||||
|
||||
unsigned int getDelayNum() const { return _delayNum; }
|
||||
void setDelayNum(unsigned int delayNum);
|
||||
|
||||
unsigned int getDelayDen() const { return _delayDen; }
|
||||
void setDelayDen(unsigned int delayDen);
|
||||
|
||||
std::vector<png_bytep>& getRows() { return _rows; }
|
||||
|
||||
private:
|
||||
unsigned char* _pixels;
|
||||
unsigned int _width;
|
||||
unsigned int _height;
|
||||
unsigned char _colorType;
|
||||
rgb _palette[256];
|
||||
unsigned char _transparency[256];
|
||||
int _paletteSize;
|
||||
int _transparencySize;
|
||||
unsigned int _delayNum;
|
||||
unsigned int _delayDen;
|
||||
std::vector<png_bytep> _rows;
|
||||
};
|
||||
|
||||
class PngDecoder CV_FINAL : public BaseImageDecoder
|
||||
{
|
||||
public:
|
||||
|
||||
PngDecoder();
|
||||
virtual ~PngDecoder();
|
||||
|
||||
bool readData( Mat& img ) CV_OVERRIDE;
|
||||
bool readHeader() CV_OVERRIDE;
|
||||
void close();
|
||||
bool nextPage() CV_OVERRIDE;
|
||||
|
||||
ImageDecoder newDecoder() const CV_OVERRIDE;
|
||||
|
||||
protected:
|
||||
|
||||
static void readDataFromBuf(void* png_ptr, uchar* dst, size_t size);
|
||||
static void info_fn(png_structp png_ptr, png_infop info_ptr);
|
||||
static void row_fn(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass);
|
||||
bool processing_start(void* frame_ptr, const Mat& img);
|
||||
bool processing_finish();
|
||||
void compose_frame(std::vector<png_bytep>& rows_dst, const std::vector<png_bytep>& rows_src, unsigned char bop, uint32_t x, uint32_t y, uint32_t w, uint32_t h, Mat& img);
|
||||
size_t read_from_io(void* _Buffer, size_t _ElementSize, size_t _ElementCount);
|
||||
uint32_t read_chunk(Chunk& chunk);
|
||||
|
||||
struct PngPtrs {
|
||||
public:
|
||||
PngPtrs() {
|
||||
png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
|
||||
if (png_ptr) {
|
||||
info_ptr = png_create_info_struct( png_ptr );
|
||||
end_info = png_create_info_struct( png_ptr );
|
||||
} else {
|
||||
info_ptr = end_info = nullptr;
|
||||
}
|
||||
}
|
||||
~PngPtrs() {
|
||||
clear();
|
||||
}
|
||||
PngPtrs& operator=(PngPtrs&& other) {
|
||||
clear();
|
||||
png_ptr = other.png_ptr;
|
||||
info_ptr = other.info_ptr;
|
||||
end_info = other.end_info;
|
||||
other.png_ptr = nullptr;
|
||||
other.info_ptr = other.end_info = nullptr;
|
||||
return *this;
|
||||
}
|
||||
void clear() {
|
||||
if (png_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
png_ptr = nullptr;
|
||||
info_ptr = end_info = nullptr;
|
||||
}
|
||||
}
|
||||
png_structp getPng() const { return png_ptr; }
|
||||
png_infop getInfo() const { return info_ptr; }
|
||||
png_infop getEndInfo() const { return end_info; }
|
||||
private:
|
||||
png_structp png_ptr; // pointer to decompression structure
|
||||
png_infop info_ptr; // pointer to image information structure
|
||||
png_infop end_info; // pointer to one more image information structure
|
||||
};
|
||||
|
||||
PngPtrs m_png_ptrs;
|
||||
int m_bit_depth;
|
||||
void* m_png_ptr; // pointer to decompression structure
|
||||
void* m_info_ptr; // pointer to image information structure
|
||||
void* m_end_info; // pointer to one more image information structure
|
||||
FILE* m_f;
|
||||
int m_color_type;
|
||||
Chunk m_chunkIHDR;
|
||||
int m_frame_no;
|
||||
size_t m_buf_pos;
|
||||
std::vector<Chunk> m_chunksInfo;
|
||||
APNGFrame frameRaw;
|
||||
APNGFrame frameNext;
|
||||
APNGFrame frameCur;
|
||||
Mat m_mat_raw;
|
||||
Mat m_mat_next;
|
||||
uint32_t w0;
|
||||
uint32_t h0;
|
||||
uint32_t x0;
|
||||
uint32_t y0;
|
||||
uint32_t delay_num;
|
||||
uint32_t delay_den;
|
||||
uint32_t dop;
|
||||
uint32_t bop;
|
||||
bool m_is_fcTL_loaded;
|
||||
bool m_is_IDAT_loaded;
|
||||
};
|
||||
|
||||
|
||||
@@ -84,14 +211,39 @@ public:
|
||||
PngEncoder();
|
||||
virtual ~PngEncoder();
|
||||
|
||||
bool isFormatSupported( int depth ) const CV_OVERRIDE;
|
||||
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
|
||||
bool isFormatSupported( int depth ) const CV_OVERRIDE;
|
||||
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
|
||||
bool writeanimation(const Animation& animinfo, const std::vector<int>& params) CV_OVERRIDE;
|
||||
|
||||
ImageEncoder newEncoder() const CV_OVERRIDE;
|
||||
|
||||
protected:
|
||||
static void writeDataToBuf(void* png_ptr, uchar* src, size_t size);
|
||||
static void writeDataToBuf(void* png_ptr, unsigned char* src, size_t size);
|
||||
static void flushBuf(void* png_ptr);
|
||||
size_t write_to_io(void const* _Buffer, size_t _ElementSize, size_t _ElementCount, FILE* _Stream);
|
||||
|
||||
private:
|
||||
void writeChunk(FILE* f, const char* name, unsigned char* data, uint32_t length);
|
||||
void writeIDATs(FILE* f, int frame, unsigned char* data, uint32_t length, uint32_t idat_size);
|
||||
void processRect(unsigned char* row, int rowbytes, int bpp, int stride, int h, unsigned char* rows);
|
||||
void deflateRectFin(unsigned char* zbuf, uint32_t* zsize, int bpp, int stride, unsigned char* rows, int zbuf_size, int n);
|
||||
void deflateRectOp(unsigned char* pdata, int x, int y, int w, int h, int bpp, int stride, int zbuf_size, int n);
|
||||
bool getRect(uint32_t w, uint32_t h, unsigned char* pimage1, unsigned char* pimage2, unsigned char* ptemp, uint32_t bpp, uint32_t stride, int zbuf_size, uint32_t has_tcolor, uint32_t tcolor, int n);
|
||||
|
||||
AutoBuffer<unsigned char> op_zbuf1;
|
||||
AutoBuffer<unsigned char> op_zbuf2;
|
||||
AutoBuffer<unsigned char> row_buf;
|
||||
AutoBuffer<unsigned char> sub_row;
|
||||
AutoBuffer<unsigned char> up_row;
|
||||
AutoBuffer<unsigned char> avg_row;
|
||||
AutoBuffer<unsigned char> paeth_row;
|
||||
z_stream op_zstream1;
|
||||
z_stream op_zstream2;
|
||||
OP op[6];
|
||||
rgb palette[256];
|
||||
unsigned char trns[256];
|
||||
uint32_t palsize, trnssize;
|
||||
uint32_t next_seq_num;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -44,17 +44,15 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include <webp/decode.h>
|
||||
#include <webp/encode.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "grfmt_webp.hpp"
|
||||
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
#include <opencv2/core/utils/configuration.private.hpp>
|
||||
#include <webp/decode.h>
|
||||
#include <webp/encode.h>
|
||||
#include <webp/demux.h>
|
||||
#include <webp/mux.h>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -67,12 +65,18 @@ static const size_t WEBP_HEADER_SIZE = 32;
|
||||
WebPDecoder::WebPDecoder()
|
||||
{
|
||||
m_buf_supported = true;
|
||||
channels = 0;
|
||||
fs_size = 0;
|
||||
m_has_animation = false;
|
||||
m_previous_timestamp = 0;
|
||||
}
|
||||
|
||||
WebPDecoder::~WebPDecoder() {}
|
||||
|
||||
void WebPDecoder::UniquePtrDeleter::operator()(WebPAnimDecoder* decoder) const
|
||||
{
|
||||
WebPAnimDecoderDelete(decoder);
|
||||
}
|
||||
|
||||
size_t WebPDecoder::signatureLength() const
|
||||
{
|
||||
return WEBP_HEADER_SIZE;
|
||||
@@ -102,6 +106,11 @@ ImageDecoder WebPDecoder::newDecoder() const
|
||||
|
||||
bool WebPDecoder::readHeader()
|
||||
{
|
||||
if (m_has_animation)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t header[WEBP_HEADER_SIZE] = { 0 };
|
||||
if (m_buf.empty())
|
||||
{
|
||||
@@ -124,28 +133,49 @@ bool WebPDecoder::readHeader()
|
||||
}
|
||||
|
||||
WebPBitstreamFeatures features;
|
||||
if (VP8_STATUS_OK == WebPGetFeatures(header, sizeof(header), &features))
|
||||
if (VP8_STATUS_OK < WebPGetFeatures(header, sizeof(header), &features)) return false;
|
||||
|
||||
m_has_animation = features.has_animation == 1;
|
||||
|
||||
if (m_has_animation)
|
||||
{
|
||||
CV_CheckEQ(features.has_animation, 0, "WebP backend does not support animated webp images");
|
||||
|
||||
m_width = features.width;
|
||||
m_height = features.height;
|
||||
|
||||
if (features.has_alpha)
|
||||
if (m_buf.empty())
|
||||
{
|
||||
m_type = CV_8UC4;
|
||||
channels = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_type = CV_8UC3;
|
||||
channels = 3;
|
||||
fs.seekg(0, std::ios::beg); CV_Assert(fs && "File stream error");
|
||||
data.create(1, validateToInt(fs_size), CV_8UC1);
|
||||
fs.read((char*)data.ptr(), fs_size);
|
||||
CV_Assert(fs && "Can't read file data");
|
||||
fs.close();
|
||||
}
|
||||
|
||||
return true;
|
||||
CV_Assert(data.type() == CV_8UC1); CV_Assert(data.rows == 1);
|
||||
|
||||
WebPData webp_data;
|
||||
webp_data.bytes = (const uint8_t*)data.ptr();
|
||||
webp_data.size = data.total();
|
||||
|
||||
WebPAnimDecoderOptions dec_options;
|
||||
WebPAnimDecoderOptionsInit(&dec_options);
|
||||
|
||||
dec_options.color_mode = m_use_rgb ? MODE_RGBA : MODE_BGRA;
|
||||
anim_decoder.reset(WebPAnimDecoderNew(&webp_data, &dec_options));
|
||||
CV_Assert(anim_decoder.get() && "Error parsing image");
|
||||
|
||||
WebPAnimInfo anim_info;
|
||||
WebPAnimDecoderGetInfo(anim_decoder.get(), &anim_info);
|
||||
m_animation.loop_count = anim_info.loop_count;
|
||||
|
||||
m_animation.bgcolor[0] = (anim_info.bgcolor >> 24) & 0xFF;
|
||||
m_animation.bgcolor[1] = (anim_info.bgcolor >> 16) & 0xFF;
|
||||
m_animation.bgcolor[2] = (anim_info.bgcolor >> 8) & 0xFF;
|
||||
m_animation.bgcolor[3] = anim_info.bgcolor & 0xFF;
|
||||
m_frame_count = anim_info.frame_count;
|
||||
}
|
||||
m_width = features.width;
|
||||
m_height = features.height;
|
||||
m_type = features.has_alpha ? CV_8UC4 : CV_8UC3;
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebPDecoder::readData(Mat &img)
|
||||
@@ -155,7 +185,7 @@ bool WebPDecoder::readData(Mat &img)
|
||||
CV_CheckEQ(img.cols, m_width, "");
|
||||
CV_CheckEQ(img.rows, m_height, "");
|
||||
|
||||
if (m_buf.empty())
|
||||
if (data.empty())
|
||||
{
|
||||
fs.seekg(0, std::ios::beg); CV_Assert(fs && "File stream error");
|
||||
data.create(1, validateToInt(fs_size), CV_8UC1);
|
||||
@@ -165,70 +195,96 @@ bool WebPDecoder::readData(Mat &img)
|
||||
}
|
||||
CV_Assert(data.type() == CV_8UC1); CV_Assert(data.rows == 1);
|
||||
|
||||
Mat read_img;
|
||||
CV_CheckType(img.type(), img.type() == CV_8UC1 || img.type() == CV_8UC3 || img.type() == CV_8UC4, "");
|
||||
if (img.type() != m_type || img.cols != m_width || img.rows != m_height)
|
||||
{
|
||||
Mat read_img;
|
||||
CV_CheckType(img.type(), img.type() == CV_8UC1 || img.type() == CV_8UC3 || img.type() == CV_8UC4, "");
|
||||
if (img.type() != m_type)
|
||||
read_img.create(m_height, m_width, m_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
read_img = img; // copy header
|
||||
}
|
||||
|
||||
uchar* out_data = read_img.ptr();
|
||||
size_t out_data_size = read_img.dataend - out_data;
|
||||
|
||||
uchar* res_ptr = NULL;
|
||||
|
||||
if (m_has_animation)
|
||||
{
|
||||
uint8_t* buf;
|
||||
int timestamp;
|
||||
|
||||
WebPAnimDecoderGetNext(anim_decoder.get(), &buf, ×tamp);
|
||||
Mat tmp(Size(m_width, m_height), CV_8UC4, buf);
|
||||
|
||||
if (img.type() == CV_8UC1)
|
||||
{
|
||||
read_img.create(m_height, m_width, m_type);
|
||||
cvtColor(tmp, img, COLOR_BGR2GRAY);
|
||||
}
|
||||
else
|
||||
if (img.type() == CV_8UC3)
|
||||
{
|
||||
read_img = img; // copy header
|
||||
}
|
||||
|
||||
uchar* out_data = read_img.ptr();
|
||||
size_t out_data_size = read_img.dataend - out_data;
|
||||
|
||||
uchar *res_ptr = NULL;
|
||||
if (channels == 3)
|
||||
{
|
||||
CV_CheckTypeEQ(read_img.type(), CV_8UC3, "");
|
||||
if (m_use_rgb)
|
||||
res_ptr = WebPDecodeRGBInto(data.ptr(), data.total(), out_data,
|
||||
(int)out_data_size, (int)read_img.step);
|
||||
else
|
||||
res_ptr = WebPDecodeBGRInto(data.ptr(), data.total(), out_data,
|
||||
(int)out_data_size, (int)read_img.step);
|
||||
}
|
||||
else if (channels == 4)
|
||||
{
|
||||
CV_CheckTypeEQ(read_img.type(), CV_8UC4, "");
|
||||
if (m_use_rgb)
|
||||
res_ptr = WebPDecodeRGBAInto(data.ptr(), data.total(), out_data,
|
||||
(int)out_data_size, (int)read_img.step);
|
||||
else
|
||||
res_ptr = WebPDecodeBGRAInto(data.ptr(), data.total(), out_data,
|
||||
(int)out_data_size, (int)read_img.step);
|
||||
}
|
||||
|
||||
if (res_ptr != out_data)
|
||||
return false;
|
||||
|
||||
if (read_img.data == img.data && img.type() == m_type)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
else if (img.type() == CV_8UC1)
|
||||
{
|
||||
cvtColor(read_img, img, COLOR_BGR2GRAY);
|
||||
}
|
||||
else if (img.type() == CV_8UC3 && m_type == CV_8UC4)
|
||||
{
|
||||
cvtColor(read_img, img, COLOR_BGRA2BGR);
|
||||
}
|
||||
else if (img.type() == CV_8UC4 && m_type == CV_8UC3)
|
||||
{
|
||||
cvtColor(read_img, img, COLOR_BGR2BGRA);
|
||||
cvtColor(tmp, img, COLOR_BGRA2BGR);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Error(Error::StsInternal, "");
|
||||
}
|
||||
tmp.copyTo(img);
|
||||
|
||||
m_animation.durations.push_back(timestamp - m_previous_timestamp);
|
||||
m_previous_timestamp = timestamp;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_type == CV_8UC3)
|
||||
{
|
||||
CV_CheckTypeEQ(read_img.type(), CV_8UC3, "");
|
||||
if (m_use_rgb)
|
||||
res_ptr = WebPDecodeRGBInto(data.ptr(), data.total(), out_data,
|
||||
(int)out_data_size, (int)read_img.step);
|
||||
else
|
||||
res_ptr = WebPDecodeBGRInto(data.ptr(), data.total(), out_data,
|
||||
(int)out_data_size, (int)read_img.step);
|
||||
}
|
||||
else if (m_type == CV_8UC4)
|
||||
{
|
||||
CV_CheckTypeEQ(read_img.type(), CV_8UC4, "");
|
||||
if (m_use_rgb)
|
||||
res_ptr = WebPDecodeRGBAInto(data.ptr(), data.total(), out_data,
|
||||
(int)out_data_size, (int)read_img.step);
|
||||
else
|
||||
res_ptr = WebPDecodeBGRAInto(data.ptr(), data.total(), out_data,
|
||||
(int)out_data_size, (int)read_img.step);
|
||||
}
|
||||
|
||||
if (res_ptr != out_data)
|
||||
return false;
|
||||
|
||||
if (read_img.data == img.data && img.type() == m_type)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
else if (img.type() == CV_8UC1)
|
||||
{
|
||||
cvtColor(read_img, img, COLOR_BGR2GRAY);
|
||||
}
|
||||
else if (img.type() == CV_8UC3 && m_type == CV_8UC4)
|
||||
{
|
||||
cvtColor(read_img, img, COLOR_BGRA2BGR);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Error(Error::StsInternal, "");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebPDecoder::nextPage()
|
||||
{
|
||||
// Prepare the next page, if any.
|
||||
return WebPAnimDecoderHasMoreFrames(anim_decoder.get()) > 0;
|
||||
}
|
||||
|
||||
WebPEncoder::WebPEncoder()
|
||||
{
|
||||
m_description = "WebP files (*.webp)";
|
||||
@@ -312,23 +368,138 @@ bool WebPEncoder::write(const Mat& img, const std::vector<int>& params)
|
||||
#endif
|
||||
|
||||
CV_Assert(size > 0);
|
||||
|
||||
size_t bytes_written = 0;
|
||||
if (m_buf)
|
||||
{
|
||||
m_buf->resize(size);
|
||||
memcpy(&(*m_buf)[0], out, size);
|
||||
bytes_written = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE *fd = fopen(m_filename.c_str(), "wb");
|
||||
if (fd != NULL)
|
||||
{
|
||||
fwrite(out, size, sizeof(uint8_t), fd);
|
||||
bytes_written = fwrite(out, sizeof(uint8_t), size, fd);
|
||||
if (size != bytes_written)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, cv::format("Only %zu or %zu bytes are written\n",bytes_written, size));
|
||||
}
|
||||
fclose(fd); fd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return size > 0;
|
||||
return (size > 0) && (bytes_written == size);
|
||||
}
|
||||
|
||||
bool WebPEncoder::writeanimation(const Animation& animation, const std::vector<int>& params)
|
||||
{
|
||||
CV_CheckDepthEQ(animation.frames[0].depth(), CV_8U, "WebP codec supports only 8-bit unsigned images");
|
||||
int ok = 0;
|
||||
int timestamp = 0;
|
||||
const int width = animation.frames[0].cols, height = animation.frames[0].rows;
|
||||
|
||||
WebPAnimEncoderOptions anim_config;
|
||||
WebPConfig config;
|
||||
WebPPicture pic;
|
||||
WebPData webp_data;
|
||||
|
||||
WebPDataInit(&webp_data);
|
||||
if (!WebPAnimEncoderOptionsInit(&anim_config) ||
|
||||
!WebPConfigInit(&config) ||
|
||||
!WebPPictureInit(&pic)) {
|
||||
CV_LOG_ERROR(NULL, "Library version mismatch!\n");
|
||||
WebPDataClear(&webp_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
int bgvalue = (static_cast<int>(animation.bgcolor[0]) & 0xFF) << 24 |
|
||||
(static_cast<int>(animation.bgcolor[1]) & 0xFF) << 16 |
|
||||
(static_cast<int>(animation.bgcolor[2]) & 0xFF) << 8 |
|
||||
(static_cast<int>(animation.bgcolor[3]) & 0xFF);
|
||||
|
||||
anim_config.anim_params.bgcolor = bgvalue;
|
||||
anim_config.anim_params.loop_count = animation.loop_count;
|
||||
|
||||
if (params.size() > 1)
|
||||
{
|
||||
if (params[0] == IMWRITE_WEBP_QUALITY)
|
||||
{
|
||||
config.lossless = 0;
|
||||
config.quality = static_cast<float>(params[1]);
|
||||
if (config.quality < 1.0f)
|
||||
{
|
||||
config.quality = 1.0f;
|
||||
}
|
||||
if (config.quality >= 100.0f)
|
||||
{
|
||||
config.lossless = 1;
|
||||
}
|
||||
}
|
||||
anim_config.minimize_size = 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<WebPAnimEncoder, void (*)(WebPAnimEncoder*)> anim_encoder(
|
||||
WebPAnimEncoderNew(width, height, &anim_config), WebPAnimEncoderDelete);
|
||||
|
||||
pic.width = width;
|
||||
pic.height = height;
|
||||
pic.use_argb = 1;
|
||||
pic.argb_stride = width;
|
||||
WebPEncode(&config, &pic);
|
||||
|
||||
bool is_input_rgba = animation.frames[0].channels() == 4;
|
||||
Size canvas_size = Size(animation.frames[0].cols,animation.frames[0].rows);
|
||||
|
||||
for (size_t i = 0; i < animation.frames.size(); i++)
|
||||
{
|
||||
Mat argb;
|
||||
CV_Assert(canvas_size == Size(animation.frames[i].cols,animation.frames[i].rows));
|
||||
if (is_input_rgba)
|
||||
pic.argb = (uint32_t*)animation.frames[i].data;
|
||||
else
|
||||
{
|
||||
cvtColor(animation.frames[i], argb, COLOR_BGR2BGRA);
|
||||
pic.argb = (uint32_t*)argb.data;
|
||||
}
|
||||
ok = WebPAnimEncoderAdd(anim_encoder.get(), &pic, timestamp, &config);
|
||||
timestamp += animation.durations[i];
|
||||
}
|
||||
|
||||
// add a last fake frame to signal the last duration
|
||||
ok = ok & WebPAnimEncoderAdd(anim_encoder.get(), NULL, timestamp, NULL);
|
||||
ok = ok & WebPAnimEncoderAssemble(anim_encoder.get(), &webp_data);
|
||||
|
||||
size_t bytes_written = 0;
|
||||
if (ok)
|
||||
{
|
||||
if (m_buf)
|
||||
{
|
||||
m_buf->resize(webp_data.size);
|
||||
memcpy(&(*m_buf)[0], webp_data.bytes, webp_data.size);
|
||||
bytes_written = webp_data.size;
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE* fd = fopen(m_filename.c_str(), "wb");
|
||||
if (fd != NULL)
|
||||
{
|
||||
bytes_written = fwrite(webp_data.bytes, sizeof(uint8_t), webp_data.size, fd);
|
||||
if (webp_data.size != bytes_written)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, cv::format("Only %zu or %zu bytes are written\n",bytes_written, webp_data.size));
|
||||
}
|
||||
fclose(fd); fd = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool status = (ok > 0) && (webp_data.size == bytes_written);
|
||||
|
||||
// free resources
|
||||
WebPDataClear(&webp_data);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
|
||||
#include <fstream>
|
||||
|
||||
struct WebPAnimDecoder;
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
@@ -61,6 +63,7 @@ public:
|
||||
|
||||
bool readData( Mat& img ) CV_OVERRIDE;
|
||||
bool readHeader() CV_OVERRIDE;
|
||||
bool nextPage() CV_OVERRIDE;
|
||||
|
||||
size_t signatureLength() const CV_OVERRIDE;
|
||||
bool checkSignature( const String& signature) const CV_OVERRIDE;
|
||||
@@ -68,10 +71,16 @@ public:
|
||||
ImageDecoder newDecoder() const CV_OVERRIDE;
|
||||
|
||||
protected:
|
||||
struct UniquePtrDeleter {
|
||||
void operator()(WebPAnimDecoder* decoder) const;
|
||||
};
|
||||
|
||||
std::ifstream fs;
|
||||
size_t fs_size;
|
||||
Mat data;
|
||||
int channels;
|
||||
std::unique_ptr<WebPAnimDecoder, UniquePtrDeleter> anim_decoder;
|
||||
bool m_has_animation;
|
||||
int m_previous_timestamp;
|
||||
};
|
||||
|
||||
class WebPEncoder CV_FINAL : public BaseImageEncoder
|
||||
@@ -81,6 +90,7 @@ public:
|
||||
~WebPEncoder() CV_OVERRIDE;
|
||||
|
||||
bool write(const Mat& img, const std::vector<int>& params) CV_OVERRIDE;
|
||||
bool writeanimation(const Animation& animation, const std::vector<int>& params) CV_OVERRIDE;
|
||||
|
||||
ImageEncoder newEncoder() const CV_OVERRIDE;
|
||||
};
|
||||
|
||||
@@ -45,8 +45,10 @@
|
||||
#include "grfmt_base.hpp"
|
||||
#include "grfmt_avif.hpp"
|
||||
#include "grfmt_bmp.hpp"
|
||||
#include "grfmt_gif.hpp"
|
||||
#include "grfmt_sunras.hpp"
|
||||
#include "grfmt_jpeg.hpp"
|
||||
#include "grfmt_jpegxl.hpp"
|
||||
#include "grfmt_pxm.hpp"
|
||||
#include "grfmt_pfm.hpp"
|
||||
#include "grfmt_tiff.hpp"
|
||||
|
||||
@@ -151,14 +151,18 @@ struct ImageCodecInitializer
|
||||
*/
|
||||
ImageCodecInitializer()
|
||||
{
|
||||
#ifdef HAVE_AVIF
|
||||
decoders.push_back(makePtr<AvifDecoder>());
|
||||
encoders.push_back(makePtr<AvifEncoder>());
|
||||
#endif
|
||||
/// BMP Support
|
||||
decoders.push_back( makePtr<BmpDecoder>() );
|
||||
encoders.push_back( makePtr<BmpEncoder>() );
|
||||
|
||||
#ifdef HAVE_IMGCODEC_GIF
|
||||
decoders.push_back( makePtr<GifDecoder>() );
|
||||
encoders.push_back( makePtr<GifEncoder>() );
|
||||
#endif
|
||||
#ifdef HAVE_AVIF
|
||||
decoders.push_back(makePtr<AvifDecoder>());
|
||||
encoders.push_back(makePtr<AvifEncoder>());
|
||||
#endif
|
||||
#ifdef HAVE_IMGCODEC_HDR
|
||||
decoders.push_back( makePtr<HdrDecoder>() );
|
||||
encoders.push_back( makePtr<HdrEncoder>() );
|
||||
@@ -206,6 +210,10 @@ struct ImageCodecInitializer
|
||||
decoders.push_back( makePtr<Jpeg2KDecoder>() );
|
||||
encoders.push_back( makePtr<Jpeg2KEncoder>() );
|
||||
#endif
|
||||
#ifdef HAVE_JPEGXL
|
||||
decoders.push_back( makePtr<JpegXLDecoder>() );
|
||||
encoders.push_back( makePtr<JpegXLEncoder>() );
|
||||
#endif
|
||||
#ifdef HAVE_OPENJPEG
|
||||
decoders.push_back( makePtr<Jpeg2KJP2OpjDecoder>() );
|
||||
decoders.push_back( makePtr<Jpeg2KJ2KOpjDecoder>() );
|
||||
@@ -685,6 +693,117 @@ bool imreadmulti(const String& filename, std::vector<Mat>& mats, int start, int
|
||||
return imreadmulti_(filename, flags, mats, start, count);
|
||||
}
|
||||
|
||||
static bool
|
||||
imreadanimation_(const String& filename, int flags, int start, int count, Animation& animation)
|
||||
{
|
||||
bool success = false;
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
if (count < 0) {
|
||||
count = INT16_MAX;
|
||||
}
|
||||
|
||||
/// Search for the relevant decoder to handle the imagery
|
||||
ImageDecoder decoder;
|
||||
decoder = findDecoder(filename);
|
||||
|
||||
/// if no decoder was found, return false.
|
||||
if (!decoder) {
|
||||
CV_LOG_WARNING(NULL, "Decoder for " << filename << " not found!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// set the filename in the driver
|
||||
decoder->setSource(filename);
|
||||
// read the header to make sure it succeeds
|
||||
try
|
||||
{
|
||||
// read the header to make sure it succeeds
|
||||
if (!decoder->readHeader())
|
||||
return false;
|
||||
}
|
||||
catch (const cv::Exception& e)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "imreadanimation_('" << filename << "'): can't read header: " << e.what());
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "imreadanimation_('" << filename << "'): can't read header: unknown exception");
|
||||
return false;
|
||||
}
|
||||
|
||||
int current = 0;
|
||||
int frame_count = (int)decoder->getFrameCount();
|
||||
count = count + start > frame_count ? frame_count - start : count;
|
||||
|
||||
uint64 pixels = (uint64)decoder->width() * (uint64)decoder->height() * (uint64)(count + 4);
|
||||
if (pixels > CV_IO_MAX_IMAGE_PIXELS) {
|
||||
CV_LOG_WARNING(NULL, "\nyou are trying to read " << pixels <<
|
||||
" bytes that exceed CV_IO_MAX_IMAGE_PIXELS.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
while (current < start + count)
|
||||
{
|
||||
// grab the decoded type
|
||||
const int type = calcType(decoder->type(), flags);
|
||||
|
||||
// established the required input image size
|
||||
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
|
||||
|
||||
// read the image data
|
||||
Mat mat(size.height, size.width, type);
|
||||
success = false;
|
||||
try
|
||||
{
|
||||
if (decoder->readData(mat))
|
||||
success = true;
|
||||
}
|
||||
catch (const cv::Exception& e)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "imreadanimation_('" << filename << "'): can't read data: " << e.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "imreadanimation_('" << filename << "'): can't read data: unknown exception");
|
||||
}
|
||||
if (!success)
|
||||
break;
|
||||
|
||||
// optionally rotate the data if EXIF' orientation flag says so
|
||||
if ((flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED)
|
||||
{
|
||||
ApplyExifOrientation(decoder->getExifTag(ORIENTATION), mat);
|
||||
}
|
||||
|
||||
if (current >= start)
|
||||
{
|
||||
int duration = decoder->animation().durations.size() > 0 ? decoder->animation().durations.back() : 1000;
|
||||
animation.durations.push_back(duration);
|
||||
animation.frames.push_back(mat);
|
||||
}
|
||||
|
||||
if (!decoder->nextPage())
|
||||
{
|
||||
break;
|
||||
}
|
||||
++current;
|
||||
}
|
||||
animation.bgcolor = decoder->animation().bgcolor;
|
||||
animation.loop_count = decoder->animation().loop_count;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool imreadanimation(const String& filename, CV_OUT Animation& animation, int start, int count)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
return imreadanimation_(filename, IMREAD_UNCHANGED, start, count, animation);
|
||||
}
|
||||
|
||||
static
|
||||
size_t imcount_(const String& filename, int flags)
|
||||
{
|
||||
@@ -819,6 +938,55 @@ bool imwrite( const String& filename, InputArray _img,
|
||||
return imwrite_(filename, img_vec, params, false);
|
||||
}
|
||||
|
||||
static bool imwriteanimation_(const String& filename, const Animation& animation, const std::vector<int>& params)
|
||||
{
|
||||
ImageEncoder encoder = findEncoder(filename);
|
||||
if (!encoder)
|
||||
CV_Error(Error::StsError, "could not find a writer for the specified extension");
|
||||
|
||||
encoder->setDestination(filename);
|
||||
|
||||
bool code = false;
|
||||
try
|
||||
{
|
||||
code = encoder->writeanimation(animation, params);
|
||||
|
||||
if (!code)
|
||||
{
|
||||
FILE* f = fopen(filename.c_str(), "wb");
|
||||
if (!f)
|
||||
{
|
||||
if (errno == EACCES)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "imwriteanimation_('" << filename << "'): can't open file for writing: permission denied");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(f);
|
||||
remove(filename.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const cv::Exception& e)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "imwriteanimation_('" << filename << "'): can't write data: " << e.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "imwriteanimation_('" << filename << "'): can't write data: unknown exception");
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
bool imwriteanimation(const String& filename, const Animation& animation, const std::vector<int>& params)
|
||||
{
|
||||
CV_Assert(!animation.frames.empty());
|
||||
CV_Assert(animation.frames.size() == animation.durations.size());
|
||||
return imwriteanimation_(filename, animation, params);
|
||||
}
|
||||
|
||||
static bool
|
||||
imdecode_( const Mat& buf, int flags, Mat& mat )
|
||||
{
|
||||
@@ -1464,6 +1632,13 @@ ImageCollection::iterator ImageCollection::iterator::operator++(int) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Animation::Animation(int loopCount, Scalar bgColor)
|
||||
: loop_count(loopCount), bgcolor(bgColor)
|
||||
{
|
||||
if (loopCount < 0 || loopCount > 0xffff)
|
||||
this->loop_count = 0; // loop_count should be non-negative
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
|
||||
@@ -137,7 +137,11 @@ uchar* FillGrayRow1( uchar* data, uchar* indices, int len, uchar* palette );
|
||||
|
||||
CV_INLINE bool isBigEndian( void )
|
||||
{
|
||||
return (((const int*)"\0\x1\x2\x3\x4\x5\x6\x7")[0] & 255) != 0;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -0,0 +1,536 @@
|
||||
// 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
static void readFileBytes(const std::string& fname, std::vector<unsigned char>& buf)
|
||||
{
|
||||
FILE * wfile = fopen(fname.c_str(), "rb");
|
||||
if (wfile != NULL)
|
||||
{
|
||||
fseek(wfile, 0, SEEK_END);
|
||||
size_t wfile_size = ftell(wfile);
|
||||
fseek(wfile, 0, SEEK_SET);
|
||||
|
||||
buf.resize(wfile_size);
|
||||
|
||||
size_t data_size = fread(&buf[0], 1, wfile_size, wfile);
|
||||
|
||||
if(wfile)
|
||||
{
|
||||
fclose(wfile);
|
||||
}
|
||||
|
||||
EXPECT_EQ(data_size, wfile_size);
|
||||
}
|
||||
}
|
||||
|
||||
static bool fillFrames(Animation& animation, bool hasAlpha, int n = 14)
|
||||
{
|
||||
// Set the path to the test image directory and filename for loading.
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filename = root + "pngsuite/tp1n3p08.png";
|
||||
|
||||
EXPECT_TRUE(imreadanimation(filename, animation));
|
||||
EXPECT_EQ(1000, animation.durations.back());
|
||||
|
||||
if (!hasAlpha)
|
||||
cvtColor(animation.frames[0], animation.frames[0], COLOR_BGRA2BGR);
|
||||
|
||||
animation.loop_count = 0xffff; // 0xffff is the maximum value to set.
|
||||
|
||||
// Add the first frame with a duration value of 400 milliseconds.
|
||||
int duration = 80;
|
||||
animation.durations[0] = duration * 5;
|
||||
Mat image = animation.frames[0].clone();
|
||||
putText(animation.frames[0], "0", Point(5, 28), FONT_HERSHEY_SIMPLEX, .5, Scalar(100, 255, 0, 255), 2);
|
||||
|
||||
// Define a region of interest (ROI)
|
||||
Rect roi(2, 16, 26, 16);
|
||||
|
||||
// Modify the ROI in n iterations to simulate slight changes in animation frames.
|
||||
for (int i = 1; i < n; i++)
|
||||
{
|
||||
roi.x++;
|
||||
roi.width -= 2;
|
||||
RNG rng = theRNG();
|
||||
for (int x = roi.x; x < roi.x + roi.width; x++)
|
||||
for (int y = roi.y; y < roi.y + roi.height; y++)
|
||||
{
|
||||
if (hasAlpha)
|
||||
{
|
||||
Vec4b& pixel = image.at<Vec4b>(y, x);
|
||||
if (pixel[3] > 0)
|
||||
{
|
||||
if (pixel[0] > 10) pixel[0] -= (uchar)rng.uniform(2, 5);
|
||||
if (pixel[1] > 10) pixel[1] -= (uchar)rng.uniform(2, 5);
|
||||
if (pixel[2] > 10) pixel[2] -= (uchar)rng.uniform(2, 5);
|
||||
pixel[3] -= (uchar)rng.uniform(2, 5);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3b& pixel = image.at<Vec3b>(y, x);
|
||||
if (pixel[0] > 50) pixel[0] -= (uchar)rng.uniform(2, 5);
|
||||
if (pixel[1] > 50) pixel[1] -= (uchar)rng.uniform(2, 5);
|
||||
if (pixel[2] > 50) pixel[2] -= (uchar)rng.uniform(2, 5);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the duration and add the modified frame to the animation.
|
||||
duration += rng.uniform(2, 10); // Increase duration with random value (to be sure different duration values saved correctly).
|
||||
animation.frames.push_back(image.clone());
|
||||
putText(animation.frames[i], format("%d", i), Point(5, 28), FONT_HERSHEY_SIMPLEX, .5, Scalar(100, 255, 0, 255), 2);
|
||||
animation.durations.push_back(duration);
|
||||
}
|
||||
|
||||
// Add two identical frames with the same duration.
|
||||
if (animation.frames.size() > 1 && animation.frames.size() < 20)
|
||||
{
|
||||
animation.durations.push_back(++duration);
|
||||
animation.frames.push_back(animation.frames.back());
|
||||
animation.durations.push_back(++duration);
|
||||
animation.frames.push_back(animation.frames.back());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_IMGCODEC_GIF
|
||||
|
||||
TEST(Imgcodecs_Gif, imwriteanimation_rgba)
|
||||
{
|
||||
Animation s_animation, l_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, true));
|
||||
s_animation.bgcolor = Scalar(0, 0, 0, 0); // TO DO not implemented yet.
|
||||
|
||||
// Create a temporary output filename for saving the animation.
|
||||
string output = cv::tempfile(".gif");
|
||||
|
||||
// Write the animation to a .webp file and verify success.
|
||||
EXPECT_TRUE(imwriteanimation(output, s_animation));
|
||||
|
||||
// Read the animation back and compare with the original.
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation));
|
||||
|
||||
size_t expected_frame_count = s_animation.frames.size();
|
||||
|
||||
// Verify that the number of frames matches the expected count.
|
||||
EXPECT_EQ(expected_frame_count, imcount(output));
|
||||
EXPECT_EQ(expected_frame_count, l_animation.frames.size());
|
||||
|
||||
// Check that the background color and loop count match between saved and loaded animations.
|
||||
EXPECT_EQ(l_animation.bgcolor, s_animation.bgcolor); // written as BGRA order
|
||||
EXPECT_EQ(l_animation.loop_count, s_animation.loop_count);
|
||||
|
||||
// Verify that the durations of frames match.
|
||||
for (size_t i = 0; i < l_animation.frames.size() - 1; i++)
|
||||
EXPECT_EQ(cvRound(s_animation.durations[i] / 10), cvRound(l_animation.durations[i] / 10));
|
||||
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation, 5, 3));
|
||||
EXPECT_EQ(expected_frame_count + 3, l_animation.frames.size());
|
||||
EXPECT_EQ(l_animation.frames.size(), l_animation.durations.size());
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[5], l_animation.frames[16], NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[6], l_animation.frames[17], NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[7], l_animation.frames[18], NORM_INF));
|
||||
|
||||
// Verify whether the imread function successfully loads the first frame
|
||||
Mat frame = imread(output, IMREAD_UNCHANGED);
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[0], frame, NORM_INF));
|
||||
|
||||
std::vector<uchar> buf;
|
||||
readFileBytes(output, buf);
|
||||
vector<Mat> webp_frames;
|
||||
|
||||
EXPECT_TRUE(imdecodemulti(buf, IMREAD_UNCHANGED, webp_frames));
|
||||
EXPECT_EQ(expected_frame_count, webp_frames.size());
|
||||
|
||||
// Clean up by removing the temporary file.
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
}
|
||||
|
||||
#endif // HAVE_IMGCODEC_GIF
|
||||
|
||||
#ifdef HAVE_WEBP
|
||||
|
||||
TEST(Imgcodecs_WebP, imwriteanimation_rgba)
|
||||
{
|
||||
Animation s_animation, l_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, true));
|
||||
s_animation.bgcolor = Scalar(50, 100, 150, 128); // different values for test purpose.
|
||||
|
||||
// Create a temporary output filename for saving the animation.
|
||||
string output = cv::tempfile(".webp");
|
||||
|
||||
// Write the animation to a .webp file and verify success.
|
||||
EXPECT_TRUE(imwriteanimation(output, s_animation));
|
||||
|
||||
// Read the animation back and compare with the original.
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation));
|
||||
|
||||
// Since the last frames are identical, WebP optimizes by storing only one of them,
|
||||
// and the duration value for the last frame is handled by libwebp.
|
||||
size_t expected_frame_count = s_animation.frames.size() - 2;
|
||||
|
||||
// Verify that the number of frames matches the expected count.
|
||||
EXPECT_EQ(expected_frame_count, imcount(output));
|
||||
EXPECT_EQ(expected_frame_count, l_animation.frames.size());
|
||||
|
||||
// Check that the background color and loop count match between saved and loaded animations.
|
||||
EXPECT_EQ(l_animation.bgcolor, s_animation.bgcolor); // written as BGRA order
|
||||
EXPECT_EQ(l_animation.loop_count, s_animation.loop_count);
|
||||
|
||||
// Verify that the durations of frames match.
|
||||
for (size_t i = 0; i < l_animation.frames.size() - 1; i++)
|
||||
EXPECT_EQ(s_animation.durations[i], l_animation.durations[i]);
|
||||
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation, 5, 3));
|
||||
EXPECT_EQ(expected_frame_count + 3, l_animation.frames.size());
|
||||
EXPECT_EQ(l_animation.frames.size(), l_animation.durations.size());
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[5], l_animation.frames[14], NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[6], l_animation.frames[15], NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[7], l_animation.frames[16], NORM_INF));
|
||||
|
||||
// Verify whether the imread function successfully loads the first frame
|
||||
Mat frame = imread(output, IMREAD_UNCHANGED);
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[0], frame, NORM_INF));
|
||||
|
||||
std::vector<uchar> buf;
|
||||
readFileBytes(output, buf);
|
||||
vector<Mat> webp_frames;
|
||||
|
||||
EXPECT_TRUE(imdecodemulti(buf, IMREAD_UNCHANGED, webp_frames));
|
||||
EXPECT_EQ(expected_frame_count, webp_frames.size());
|
||||
|
||||
// Clean up by removing the temporary file.
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_WebP, imwriteanimation_rgb)
|
||||
{
|
||||
Animation s_animation, l_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, false));
|
||||
|
||||
// Create a temporary output filename for saving the animation.
|
||||
string output = cv::tempfile(".webp");
|
||||
|
||||
// Write the animation to a .webp file and verify success.
|
||||
EXPECT_TRUE(imwriteanimation(output, s_animation));
|
||||
|
||||
// Read the animation back and compare with the original.
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation));
|
||||
|
||||
// Since the last frames are identical, WebP optimizes by storing only one of them,
|
||||
// and the duration value for the last frame is handled by libwebp.
|
||||
size_t expected_frame_count = s_animation.frames.size() - 2;
|
||||
|
||||
// Verify that the number of frames matches the expected count.
|
||||
EXPECT_EQ(expected_frame_count, imcount(output));
|
||||
EXPECT_EQ(expected_frame_count, l_animation.frames.size());
|
||||
|
||||
// Verify that the durations of frames match.
|
||||
for (size_t i = 0; i < l_animation.frames.size() - 1; i++)
|
||||
EXPECT_EQ(s_animation.durations[i], l_animation.durations[i]);
|
||||
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation, 5, 3));
|
||||
EXPECT_EQ(expected_frame_count + 3, l_animation.frames.size());
|
||||
EXPECT_EQ(l_animation.frames.size(), l_animation.durations.size());
|
||||
EXPECT_TRUE(cvtest::norm(l_animation.frames[5], l_animation.frames[14], NORM_INF) == 0);
|
||||
EXPECT_TRUE(cvtest::norm(l_animation.frames[6], l_animation.frames[15], NORM_INF) == 0);
|
||||
EXPECT_TRUE(cvtest::norm(l_animation.frames[7], l_animation.frames[16], NORM_INF) == 0);
|
||||
|
||||
// Verify whether the imread function successfully loads the first frame
|
||||
Mat frame = imread(output, IMREAD_COLOR);
|
||||
EXPECT_TRUE(cvtest::norm(l_animation.frames[0], frame, NORM_INF) == 0);
|
||||
|
||||
std::vector<uchar> buf;
|
||||
readFileBytes(output, buf);
|
||||
|
||||
vector<Mat> webp_frames;
|
||||
EXPECT_TRUE(imdecodemulti(buf, IMREAD_UNCHANGED, webp_frames));
|
||||
EXPECT_EQ(expected_frame_count,webp_frames.size());
|
||||
|
||||
// Clean up by removing the temporary file.
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_WebP, imwritemulti_rgba)
|
||||
{
|
||||
Animation s_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, true));
|
||||
|
||||
string output = cv::tempfile(".webp");
|
||||
ASSERT_TRUE(imwrite(output, s_animation.frames));
|
||||
vector<Mat> read_frames;
|
||||
ASSERT_TRUE(imreadmulti(output, read_frames, IMREAD_UNCHANGED));
|
||||
EXPECT_EQ(s_animation.frames.size() - 2, read_frames.size());
|
||||
EXPECT_EQ(4, s_animation.frames[0].channels());
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_WebP, imwritemulti_rgb)
|
||||
{
|
||||
Animation s_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, false));
|
||||
|
||||
string output = cv::tempfile(".webp");
|
||||
ASSERT_TRUE(imwrite(output, s_animation.frames));
|
||||
vector<Mat> read_frames;
|
||||
ASSERT_TRUE(imreadmulti(output, read_frames));
|
||||
EXPECT_EQ(s_animation.frames.size() - 2, read_frames.size());
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_WebP, imencode_rgba)
|
||||
{
|
||||
Animation s_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, true, 3));
|
||||
|
||||
std::vector<uchar> buf;
|
||||
vector<Mat> apng_frames;
|
||||
|
||||
// Test encoding and decoding the images in memory (without saving to disk).
|
||||
EXPECT_TRUE(imencode(".webp", s_animation.frames, buf));
|
||||
EXPECT_TRUE(imdecodemulti(buf, IMREAD_UNCHANGED, apng_frames));
|
||||
EXPECT_EQ(s_animation.frames.size() - 2, apng_frames.size());
|
||||
}
|
||||
|
||||
#endif // HAVE_WEBP
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
|
||||
TEST(Imgcodecs_APNG, imwriteanimation_rgba)
|
||||
{
|
||||
Animation s_animation, l_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, true));
|
||||
|
||||
// Create a temporary output filename for saving the animation.
|
||||
string output = cv::tempfile(".png");
|
||||
|
||||
// Write the animation to a .png file and verify success.
|
||||
EXPECT_TRUE(imwriteanimation(output, s_animation));
|
||||
|
||||
// Read the animation back and compare with the original.
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation));
|
||||
|
||||
size_t expected_frame_count = s_animation.frames.size() - 2;
|
||||
|
||||
// Verify that the number of frames matches the expected count.
|
||||
EXPECT_EQ(expected_frame_count, imcount(output));
|
||||
EXPECT_EQ(expected_frame_count, l_animation.frames.size());
|
||||
|
||||
for (size_t i = 0; i < l_animation.frames.size() - 1; i++)
|
||||
{
|
||||
EXPECT_EQ(s_animation.durations[i], l_animation.durations[i]);
|
||||
EXPECT_EQ(0, cvtest::norm(s_animation.frames[i], l_animation.frames[i], NORM_INF));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation, 5, 3));
|
||||
EXPECT_EQ(expected_frame_count + 3, l_animation.frames.size());
|
||||
EXPECT_EQ(l_animation.frames.size(), l_animation.durations.size());
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[5], l_animation.frames[14], NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[6], l_animation.frames[15], NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[7], l_animation.frames[16], NORM_INF));
|
||||
|
||||
// Verify whether the imread function successfully loads the first frame
|
||||
Mat frame = imread(output, IMREAD_UNCHANGED);
|
||||
EXPECT_EQ(0, cvtest::norm(l_animation.frames[0], frame, NORM_INF));
|
||||
|
||||
std::vector<uchar> buf;
|
||||
readFileBytes(output, buf);
|
||||
vector<Mat> apng_frames;
|
||||
|
||||
EXPECT_TRUE(imdecodemulti(buf, IMREAD_UNCHANGED, apng_frames));
|
||||
EXPECT_EQ(expected_frame_count, apng_frames.size());
|
||||
|
||||
apng_frames.clear();
|
||||
// Test saving the animation frames as individual still images.
|
||||
EXPECT_TRUE(imwrite(output, s_animation.frames));
|
||||
|
||||
// Read back the still images into a vector of Mats.
|
||||
EXPECT_TRUE(imreadmulti(output, apng_frames));
|
||||
|
||||
// Expect all frames written as multi-page image
|
||||
EXPECT_EQ(expected_frame_count, apng_frames.size());
|
||||
|
||||
// Clean up by removing the temporary file.
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_APNG, imwriteanimation_rgba16u)
|
||||
{
|
||||
Animation s_animation, l_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, true));
|
||||
|
||||
for (size_t i = 0; i < s_animation.frames.size(); i++)
|
||||
{
|
||||
s_animation.frames[i].convertTo(s_animation.frames[i], CV_16U, 255);
|
||||
}
|
||||
// Create a temporary output filename for saving the animation.
|
||||
string output = cv::tempfile(".png");
|
||||
|
||||
// Write the animation to a .png file and verify success.
|
||||
EXPECT_TRUE(imwriteanimation(output, s_animation));
|
||||
|
||||
// Read the animation back and compare with the original.
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation));
|
||||
|
||||
size_t expected_frame_count = s_animation.frames.size() - 2;
|
||||
|
||||
// Verify that the number of frames matches the expected count.
|
||||
EXPECT_EQ(expected_frame_count, imcount(output));
|
||||
EXPECT_EQ(expected_frame_count, l_animation.frames.size());
|
||||
|
||||
std::vector<uchar> buf;
|
||||
readFileBytes(output, buf);
|
||||
vector<Mat> apng_frames;
|
||||
|
||||
EXPECT_TRUE(imdecodemulti(buf, IMREAD_UNCHANGED, apng_frames));
|
||||
EXPECT_EQ(expected_frame_count, apng_frames.size());
|
||||
|
||||
apng_frames.clear();
|
||||
// Test saving the animation frames as individual still images.
|
||||
EXPECT_TRUE(imwrite(output, s_animation.frames));
|
||||
|
||||
// Read back the still images into a vector of Mats.
|
||||
EXPECT_TRUE(imreadmulti(output, apng_frames));
|
||||
|
||||
// Expect all frames written as multi-page image
|
||||
EXPECT_EQ(expected_frame_count, apng_frames.size());
|
||||
|
||||
// Clean up by removing the temporary file.
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_APNG, imwriteanimation_rgb)
|
||||
{
|
||||
Animation s_animation, l_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, false));
|
||||
|
||||
string output = cv::tempfile(".png");
|
||||
|
||||
// Write the animation to a .png file and verify success.
|
||||
EXPECT_TRUE(imwriteanimation(output, s_animation));
|
||||
|
||||
// Read the animation back and compare with the original.
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation));
|
||||
EXPECT_EQ(l_animation.frames.size(), s_animation.frames.size() - 2);
|
||||
for (size_t i = 0; i < l_animation.frames.size() - 1; i++)
|
||||
{
|
||||
EXPECT_EQ(0, cvtest::norm(s_animation.frames[i], l_animation.frames[i], NORM_INF));
|
||||
}
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_APNG, imwritemulti_rgba)
|
||||
{
|
||||
Animation s_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, true));
|
||||
|
||||
string output = cv::tempfile(".png");
|
||||
EXPECT_EQ(true, imwrite(output, s_animation.frames));
|
||||
vector<Mat> read_frames;
|
||||
EXPECT_EQ(true, imreadmulti(output, read_frames, IMREAD_UNCHANGED));
|
||||
EXPECT_EQ(read_frames.size(), s_animation.frames.size() - 2);
|
||||
EXPECT_EQ(imcount(output), read_frames.size());
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_APNG, imwritemulti_rgb)
|
||||
{
|
||||
Animation s_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, false));
|
||||
|
||||
string output = cv::tempfile(".png");
|
||||
ASSERT_TRUE(imwrite(output, s_animation.frames));
|
||||
vector<Mat> read_frames;
|
||||
ASSERT_TRUE(imreadmulti(output, read_frames));
|
||||
EXPECT_EQ(read_frames.size(), s_animation.frames.size() - 2);
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
|
||||
for (size_t i = 0; i < read_frames.size(); i++)
|
||||
{
|
||||
EXPECT_EQ(0, cvtest::norm(s_animation.frames[i], read_frames[i], NORM_INF));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_APNG, imwritemulti_gray)
|
||||
{
|
||||
Animation s_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, false));
|
||||
|
||||
for (size_t i = 0; i < s_animation.frames.size(); i++)
|
||||
{
|
||||
cvtColor(s_animation.frames[i], s_animation.frames[i], COLOR_BGR2GRAY);
|
||||
}
|
||||
|
||||
string output = cv::tempfile(".png");
|
||||
EXPECT_TRUE(imwrite(output, s_animation.frames));
|
||||
vector<Mat> read_frames;
|
||||
EXPECT_TRUE(imreadmulti(output, read_frames));
|
||||
EXPECT_EQ(1, read_frames[0].channels());
|
||||
read_frames.clear();
|
||||
EXPECT_TRUE(imreadmulti(output, read_frames, IMREAD_UNCHANGED));
|
||||
EXPECT_EQ(1, read_frames[0].channels());
|
||||
read_frames.clear();
|
||||
EXPECT_TRUE(imreadmulti(output, read_frames, IMREAD_COLOR));
|
||||
EXPECT_EQ(3, read_frames[0].channels());
|
||||
read_frames.clear();
|
||||
EXPECT_TRUE(imreadmulti(output, read_frames, IMREAD_GRAYSCALE));
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
|
||||
for (size_t i = 0; i < read_frames.size(); i++)
|
||||
{
|
||||
EXPECT_EQ(0, cvtest::norm(s_animation.frames[i], read_frames[i], NORM_INF));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_APNG, imwriteanimation_bgcolor)
|
||||
{
|
||||
Animation s_animation, l_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, true, 2));
|
||||
s_animation.bgcolor = Scalar(50, 100, 150, 128); // different values for test purpose.
|
||||
|
||||
// Create a temporary output filename for saving the animation.
|
||||
string output = cv::tempfile(".png");
|
||||
|
||||
// Write the animation to a .png file and verify success.
|
||||
EXPECT_TRUE(imwriteanimation(output, s_animation));
|
||||
|
||||
// Read the animation back and compare with the original.
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation));
|
||||
|
||||
// Check that the background color match between saved and loaded animations.
|
||||
EXPECT_EQ(l_animation.bgcolor, s_animation.bgcolor);
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
|
||||
EXPECT_TRUE(fillFrames(s_animation, true, 2));
|
||||
s_animation.bgcolor = Scalar();
|
||||
|
||||
output = cv::tempfile(".png");
|
||||
EXPECT_TRUE(imwriteanimation(output, s_animation));
|
||||
EXPECT_TRUE(imreadanimation(output, l_animation));
|
||||
EXPECT_EQ(l_animation.bgcolor, s_animation.bgcolor);
|
||||
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_APNG, imencode_rgba)
|
||||
{
|
||||
Animation s_animation;
|
||||
EXPECT_TRUE(fillFrames(s_animation, true, 3));
|
||||
|
||||
std::vector<uchar> buf;
|
||||
vector<Mat> read_frames;
|
||||
// Test encoding and decoding the images in memory (without saving to disk).
|
||||
EXPECT_TRUE(imencode(".png", s_animation.frames, buf));
|
||||
EXPECT_TRUE(imdecodemulti(buf, IMREAD_UNCHANGED, read_frames));
|
||||
EXPECT_EQ(read_frames.size(), s_animation.frames.size() - 2);
|
||||
}
|
||||
|
||||
#endif // HAVE_PNG
|
||||
|
||||
}} // namespace
|
||||
@@ -2,6 +2,9 @@
|
||||
// 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 <string>
|
||||
#include <vector>
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
@@ -110,7 +113,7 @@ TEST_P(Exif, exif_orientation)
|
||||
}
|
||||
}
|
||||
|
||||
const string exif_files[] =
|
||||
const std::vector<std::string> exif_files
|
||||
{
|
||||
#ifdef HAVE_JPEG
|
||||
"readwrite/testExifOrientation_1.jpg",
|
||||
|
||||
@@ -0,0 +1,357 @@
|
||||
// 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 "test_precomp.hpp"
|
||||
|
||||
#ifdef HAVE_IMGCODEC_GIF
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
const string gifsuite_files_multi[]={
|
||||
"basi3p01",
|
||||
"basi3p02",
|
||||
"basi3p04",
|
||||
"basn3p01",
|
||||
"basn3p02",
|
||||
"basn3p04",
|
||||
"ccwn3p08",
|
||||
"ch1n3p04",
|
||||
"cs3n3p08",
|
||||
"cs5n3p08",
|
||||
"cs8n3p08",
|
||||
"g03n3p04",
|
||||
"g04n3p04",
|
||||
"g05n3p04",
|
||||
"g07n3p04",
|
||||
"g10n3p04",
|
||||
"g25n3p04",
|
||||
"s32i3p04",
|
||||
"s32n3p04",
|
||||
"tp0n3p08",
|
||||
};
|
||||
|
||||
const string gifsuite_files_read_single[] = {
|
||||
"basi3p01",
|
||||
"basi3p02",
|
||||
"basi3p04",
|
||||
"basn3p01",
|
||||
"basn3p02",
|
||||
"basn3p04",
|
||||
"ccwn3p08",
|
||||
"cdfn2c08",
|
||||
"cdhn2c08",
|
||||
"cdsn2c08",
|
||||
"cdun2c08",
|
||||
"ch1n3p04",
|
||||
"cs3n3p08",
|
||||
"cs5n2c08",
|
||||
"cs5n3p08",
|
||||
"cs8n2c08",
|
||||
"cs8n3p08",
|
||||
"exif2c08",
|
||||
"g03n2c08",
|
||||
"g03n3p04",
|
||||
"g04n2c08",
|
||||
"g04n3p04",
|
||||
"g05n2c08",
|
||||
"g05n3p04",
|
||||
"g07n2c08",
|
||||
"g07n3p04",
|
||||
"g10n2c08",
|
||||
"g10n3p04"
|
||||
};
|
||||
|
||||
const string gifsuite_files_read_write_suite[]={
|
||||
"g25n2c08",
|
||||
"g25n3p04",
|
||||
"s01i3p01",
|
||||
"s01n3p01",
|
||||
"s02i3p01",
|
||||
"s02n3p01",
|
||||
"s03i3p01",
|
||||
"s03n3p01",
|
||||
"s04i3p01",
|
||||
"s04n3p01",
|
||||
"s05i3p02",
|
||||
"s05n3p02",
|
||||
"s06i3p02",
|
||||
"s06n3p02",
|
||||
"s07i3p02",
|
||||
"s07n3p02",
|
||||
"s08i3p02",
|
||||
"s08n3p02",
|
||||
"s09i3p02",
|
||||
"s09n3p02",
|
||||
"s32i3p04",
|
||||
"s32n3p04",
|
||||
"s33i3p04",
|
||||
"s33n3p04",
|
||||
"s34i3p04",
|
||||
"s34n3p04",
|
||||
"s35i3p04",
|
||||
"s35n3p04",
|
||||
"s36i3p04",
|
||||
"s36n3p04",
|
||||
"s37i3p04",
|
||||
"s37n3p04",
|
||||
"s38i3p04",
|
||||
"s38n3p04",
|
||||
"s39i3p04",
|
||||
"s39n3p04",
|
||||
"s40i3p04",
|
||||
"s40n3p04",
|
||||
"tp0n3p08",
|
||||
};
|
||||
|
||||
const std::pair<string,int> gifsuite_files_bgra[]={
|
||||
make_pair("gif_bgra1",53287),
|
||||
make_pair("gif_bgra2",52651),
|
||||
make_pair("gif_bgra3",54809),
|
||||
make_pair("gif_bgra4",57562),
|
||||
make_pair("gif_bgra5",56733),
|
||||
make_pair("gif_bgra6",52110),
|
||||
};
|
||||
|
||||
TEST(Imgcodecs_Gif, read_gif_multi)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filename = root + "gifsuite/gif_multi.gif";
|
||||
vector<cv::Mat> img_vec_8UC4;
|
||||
ASSERT_NO_THROW(cv::imreadmulti(filename, img_vec_8UC4,0,20,IMREAD_UNCHANGED));
|
||||
EXPECT_EQ(img_vec_8UC4.size(), imcount(filename));
|
||||
vector<cv::Mat> img_vec_8UC3;
|
||||
for(const auto & i : img_vec_8UC4){
|
||||
cv::Mat img_tmp;
|
||||
cvtColor(i,img_tmp,COLOR_BGRA2BGR);
|
||||
img_vec_8UC3.push_back(img_tmp);
|
||||
}
|
||||
const long unsigned int expected_size=20;
|
||||
EXPECT_EQ(img_vec_8UC3.size(),expected_size);
|
||||
for(long unsigned int i=0;i<img_vec_8UC3.size();i++){
|
||||
cv::Mat img=img_vec_8UC3[i];
|
||||
const string png_filename = root + "pngsuite/" + gifsuite_files_multi[i] + ".png";
|
||||
cv::Mat img_png;
|
||||
ASSERT_NO_THROW(img_png = imread(png_filename,IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(img_png.empty());
|
||||
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, img_png);
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<string> Imgcodecs_Gif_GifSuite_SingleFrame;
|
||||
|
||||
TEST_P(Imgcodecs_Gif_GifSuite_SingleFrame, read_gif_single)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filename = root + "gifsuite/" + GetParam() + ".gif";
|
||||
const string png_filename=root + "pngsuite/" + GetParam() + ".png";
|
||||
const long unsigned int expected_size = 1;
|
||||
|
||||
EXPECT_EQ(expected_size, imcount(filename));
|
||||
cv::Mat img_8UC4;
|
||||
ASSERT_NO_THROW(img_8UC4 = cv::imread(filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(img_8UC4.empty());
|
||||
cv::Mat img_8UC3;
|
||||
ASSERT_NO_THROW(cvtColor(img_8UC4, img_8UC3, COLOR_BGRA2BGR));
|
||||
cv::Mat img_png;
|
||||
ASSERT_NO_THROW(img_png = cv::imread(png_filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(img_png.empty());
|
||||
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img_8UC3, img_png);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Gif_GifSuite_SingleFrame,
|
||||
testing::ValuesIn(gifsuite_files_read_single));
|
||||
|
||||
TEST(Imgcodecs_Gif, read_gif_big){
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string gif_filename = root + "gifsuite/gif_big.gif";
|
||||
const string png_filename = root + "gifsuite/gif_big.png";
|
||||
cv::Mat img_8UC4;
|
||||
ASSERT_NO_THROW(img_8UC4 = imread(gif_filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(img_8UC4.empty());
|
||||
cv::Mat img_8UC3;
|
||||
const int expected_col=1303;
|
||||
const int expected_row=1391;
|
||||
EXPECT_EQ(expected_col, img_8UC4.cols);
|
||||
EXPECT_EQ(expected_row, img_8UC4.rows);
|
||||
ASSERT_NO_THROW(cvtColor(img_8UC4, img_8UC3,COLOR_BGRA2BGR));
|
||||
EXPECT_EQ(expected_col, img_8UC3.cols);
|
||||
EXPECT_EQ(expected_row, img_8UC3.rows);
|
||||
cv::Mat img_png;
|
||||
ASSERT_NO_THROW(img_png=imread(png_filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(img_png.empty());
|
||||
cv::Mat img_png_8UC3;
|
||||
ASSERT_NO_THROW(cvtColor(img_png,img_png_8UC3, COLOR_BGRA2BGR));
|
||||
EXPECT_EQ(img_8UC3.size, img_png_8UC3.size);
|
||||
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img_8UC3, img_png_8UC3);
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<std::pair<string,int>> Imgcodecs_Gif_GifSuite_SingleFrame_BGRA;
|
||||
|
||||
TEST_P(Imgcodecs_Gif_GifSuite_SingleFrame_BGRA, read_gif_single_bgra){
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string gif_filename = root + "gifsuite/" + GetParam().first + ".gif";
|
||||
const string png_filename = root + "gifsuite/" + GetParam().first + ".png";
|
||||
cv::Mat gif_img;
|
||||
cv::Mat png_img;
|
||||
ASSERT_NO_THROW(gif_img = cv::imread(gif_filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(gif_img.empty());
|
||||
ASSERT_NO_THROW(png_img = cv::imread(png_filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(png_img.empty());
|
||||
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), gif_img, png_img);
|
||||
int transparent_count = 0;
|
||||
for(int i=0; i<gif_img.rows; i++){
|
||||
for(int j=0; j<gif_img.cols; j++){
|
||||
cv::Vec4b pixel1 = gif_img.at<cv::Vec4b>(i,j);
|
||||
if((int)(pixel1[3]) == 0){
|
||||
transparent_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(transparent_count,GetParam().second);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Gif_GifSuite_SingleFrame_BGRA ,
|
||||
testing::ValuesIn(gifsuite_files_bgra));
|
||||
|
||||
TEST(Imgcodecs_Gif,read_gif_multi_bgra){
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string gif_filename = root + "gifsuite/gif_multi_bgra.gif";
|
||||
vector<cv::Mat> img_vec;
|
||||
ASSERT_NO_THROW(cv::imreadmulti(gif_filename, img_vec, IMREAD_UNCHANGED));
|
||||
EXPECT_EQ(imcount(gif_filename), img_vec.size());
|
||||
const int fixed_transparent_count = 53211;
|
||||
for(auto & frame_count : img_vec){
|
||||
int transparent_count=0;
|
||||
for(int i=0; i<frame_count.rows; i++){
|
||||
for(int j=0; j<frame_count.cols; j++){
|
||||
cv::Vec4b pixel1 = frame_count.at<cv::Vec4b>(i,j);
|
||||
if((int)(pixel1[3]) == 0){
|
||||
transparent_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(fixed_transparent_count,transparent_count);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_Gif, read_gif_special){
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string gif_filename1 = root + "gifsuite/special1.gif";
|
||||
const string png_filename1 = root + "gifsuite/special1.png";
|
||||
const string gif_filename2 = root + "gifsuite/special2.gif";
|
||||
const string png_filename2 = root + "gifsuite/special2.png";
|
||||
cv::Mat gif_img1;
|
||||
ASSERT_NO_THROW(gif_img1 = cv::imread(gif_filename1,IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(gif_img1.empty());
|
||||
cv::Mat png_img1;
|
||||
ASSERT_NO_THROW(png_img1 = cv::imread(png_filename1,IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(png_img1.empty());
|
||||
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), gif_img1, png_img1);
|
||||
cv::Mat gif_img2;
|
||||
ASSERT_NO_THROW(gif_img2 = cv::imread(gif_filename2,IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(gif_img2.empty());
|
||||
cv::Mat png_img2;
|
||||
ASSERT_NO_THROW(png_img2 = cv::imread(png_filename2,IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(png_img2.empty());
|
||||
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), gif_img2, png_img2);
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_Gif,write_gif_flags){
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string png_filename = root + "gifsuite/special1.png";
|
||||
vector<uchar> buff;
|
||||
const int expected_rows=611;
|
||||
const int expected_cols=293;
|
||||
Mat img_gt = Mat::ones(expected_rows, expected_cols, CV_8UC1);
|
||||
vector<int> param;
|
||||
param.push_back(IMWRITE_GIF_QUALITY);
|
||||
param.push_back(7);
|
||||
param.push_back(IMWRITE_GIF_DITHER);
|
||||
param.push_back(2);
|
||||
EXPECT_NO_THROW(imencode(".png", img_gt, buff, param));
|
||||
Mat img;
|
||||
EXPECT_NO_THROW(img = imdecode(buff, IMREAD_ANYDEPTH)); // hang
|
||||
EXPECT_FALSE(img.empty());
|
||||
EXPECT_EQ(img.cols, expected_cols);
|
||||
EXPECT_EQ(img.rows, expected_rows);
|
||||
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, img_gt);
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_Gif, write_gif_big) {
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string png_filename = root + "gifsuite/gif_big.png";
|
||||
const string gif_filename = cv::tempfile(".png");
|
||||
cv::Mat img;
|
||||
ASSERT_NO_THROW(img = cv::imread(png_filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(img.empty());
|
||||
EXPECT_EQ(1303, img.cols);
|
||||
EXPECT_EQ(1391, img.rows);
|
||||
ASSERT_NO_THROW(imwrite(gif_filename, img));
|
||||
cv::Mat img_gif;
|
||||
ASSERT_NO_THROW(img_gif = cv::imread(gif_filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(img_gif.empty());
|
||||
EXPECT_EQ(1303, img_gif.cols);
|
||||
EXPECT_EQ(1391, img_gif.rows);
|
||||
EXPECT_EQ(0, remove(gif_filename.c_str()));
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<string> Imgcodecs_Gif_GifSuite_Read_Write_Suite;
|
||||
|
||||
TEST_P(Imgcodecs_Gif_GifSuite_Read_Write_Suite ,read_gif_single)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string png_filename = root + "pngsuite/"+GetParam()+".png";
|
||||
const string gif_filename = cv::tempfile(".gif");
|
||||
cv::Mat img;
|
||||
ASSERT_NO_THROW(img = cv::imread(png_filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(img.empty());
|
||||
vector<int> param;
|
||||
param.push_back(IMWRITE_GIF_QUALITY);
|
||||
param.push_back(8);
|
||||
param.push_back(IMWRITE_GIF_DITHER);
|
||||
param.push_back(3);
|
||||
ASSERT_NO_THROW(imwrite(gif_filename, img, param));
|
||||
cv::Mat img_gif;
|
||||
ASSERT_NO_THROW(img_gif = cv::imread(gif_filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(img_gif.empty());
|
||||
cv::Mat img_8UC3;
|
||||
ASSERT_NO_THROW(cv::cvtColor(img_gif, img_8UC3, COLOR_BGRA2BGR));
|
||||
EXPECT_PRED_FORMAT2(cvtest::MatComparator(29, 0), img, img_8UC3);
|
||||
EXPECT_EQ(0, remove(gif_filename.c_str()));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Gif_GifSuite_Read_Write_Suite ,
|
||||
testing::ValuesIn(gifsuite_files_read_write_suite));
|
||||
|
||||
TEST(Imgcodecs_Gif, write_gif_multi) {
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string gif_filename = cv::tempfile(".gif");
|
||||
vector<cv::Mat> img_vec;
|
||||
for (long unsigned int i = 0; i < 20; i++) {
|
||||
const string png_filename = root + "pngsuite/" + gifsuite_files_multi[i] + ".png";
|
||||
cv::Mat img;
|
||||
ASSERT_NO_THROW(img = cv::imread(png_filename, IMREAD_UNCHANGED));
|
||||
ASSERT_FALSE(img.empty());
|
||||
img_vec.push_back(img);
|
||||
}
|
||||
vector<int> param;
|
||||
param.push_back(IMWRITE_GIF_QUALITY);
|
||||
param.push_back(8);
|
||||
param.push_back(IMWRITE_GIF_DITHER);
|
||||
param.push_back(3);
|
||||
ASSERT_NO_THROW(cv::imwritemulti(gif_filename, img_vec, param));
|
||||
vector<cv::Mat> img_vec_gif;
|
||||
ASSERT_NO_THROW(cv::imreadmulti(gif_filename, img_vec_gif));
|
||||
EXPECT_EQ(img_vec.size(), img_vec_gif.size());
|
||||
for (long unsigned int i = 0; i < img_vec.size(); i++) {
|
||||
cv::Mat img_8UC3;
|
||||
ASSERT_NO_THROW(cv::cvtColor(img_vec_gif[i], img_8UC3, COLOR_BGRA2BGR));
|
||||
EXPECT_PRED_FORMAT2(cvtest::MatComparator(29, 0), img_vec[i], img_8UC3);
|
||||
}
|
||||
EXPECT_EQ(0, remove(gif_filename.c_str()));
|
||||
}
|
||||
|
||||
}//opencv_test
|
||||
}//namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
// 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 "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#ifdef HAVE_JPEGXL
|
||||
|
||||
typedef tuple<perf::MatType, int> MatType_and_Distance;
|
||||
typedef testing::TestWithParam<MatType_and_Distance> Imgcodecs_JpegXL_MatType;
|
||||
|
||||
TEST_P(Imgcodecs_JpegXL_MatType, write_read)
|
||||
{
|
||||
const int matType = get<0>(GetParam());
|
||||
const int distanceParam = get<1>(GetParam());
|
||||
|
||||
cv::Scalar col;
|
||||
// Jpeg XL is lossy compression.
|
||||
// There may be small differences in decoding results by environments.
|
||||
double th;
|
||||
|
||||
switch( CV_MAT_DEPTH(matType) )
|
||||
{
|
||||
case CV_16U:
|
||||
col = cv::Scalar(124 * 256, 76 * 256, 42 * 256, 192 * 256 );
|
||||
th = 656; // = 65535 / 100;
|
||||
break;
|
||||
case CV_32F:
|
||||
col = cv::Scalar(0.486, 0.298, 0.165, 0.75);
|
||||
th = 1.0 / 100.0;
|
||||
break;
|
||||
default:
|
||||
case CV_8U:
|
||||
col = cv::Scalar(124, 76, 42, 192);
|
||||
th = 3; // = 255 / 100 (1%);
|
||||
break;
|
||||
}
|
||||
|
||||
// If increasing distanceParam, threshold should be increased.
|
||||
th *= (distanceParam >= 25) ? 5 : ( distanceParam > 2 ) ? 3 : (distanceParam == 2) ? 2: 1;
|
||||
|
||||
bool ret = false;
|
||||
string tmp_fname = cv::tempfile(".jxl");
|
||||
Mat img_org(320, 480, matType, col);
|
||||
vector<int> param;
|
||||
param.push_back(IMWRITE_JPEGXL_DISTANCE);
|
||||
param.push_back(distanceParam);
|
||||
EXPECT_NO_THROW(ret = imwrite(tmp_fname, img_org, param));
|
||||
EXPECT_TRUE(ret);
|
||||
Mat img_decoded;
|
||||
EXPECT_NO_THROW(img_decoded = imread(tmp_fname, IMREAD_UNCHANGED));
|
||||
EXPECT_FALSE(img_decoded.empty());
|
||||
|
||||
EXPECT_LE(cvtest::norm(img_org, img_decoded, NORM_INF), th);
|
||||
|
||||
EXPECT_EQ(0, remove(tmp_fname.c_str()));
|
||||
}
|
||||
|
||||
TEST_P(Imgcodecs_JpegXL_MatType, encode_decode)
|
||||
{
|
||||
const int matType = get<0>(GetParam());
|
||||
const int distanceParam = get<1>(GetParam());
|
||||
|
||||
cv::Scalar col;
|
||||
// Jpeg XL is lossy compression.
|
||||
// There may be small differences in decoding results by environments.
|
||||
double th;
|
||||
|
||||
// If alpha=0, libjxl modify color channels(BGR). So do not set it.
|
||||
switch( CV_MAT_DEPTH(matType) )
|
||||
{
|
||||
case CV_16U:
|
||||
col = cv::Scalar(124 * 256, 76 * 256, 42 * 256, 192 * 256 );
|
||||
th = 656; // = 65535 / 100;
|
||||
break;
|
||||
case CV_32F:
|
||||
col = cv::Scalar(0.486, 0.298, 0.165, 0.75);
|
||||
th = 1.0 / 100.0;
|
||||
break;
|
||||
default:
|
||||
case CV_8U:
|
||||
col = cv::Scalar(124, 76, 42, 192);
|
||||
th = 3; // = 255 / 100 (1%);
|
||||
break;
|
||||
}
|
||||
|
||||
// If increasing distanceParam, threshold should be increased.
|
||||
th *= (distanceParam >= 25) ? 5 : ( distanceParam > 2 ) ? 3 : (distanceParam == 2) ? 2: 1;
|
||||
|
||||
bool ret = false;
|
||||
vector<uchar> buff;
|
||||
Mat img_org(320, 480, matType, col);
|
||||
vector<int> param;
|
||||
param.push_back(IMWRITE_JPEGXL_DISTANCE);
|
||||
param.push_back(distanceParam);
|
||||
EXPECT_NO_THROW(ret = imencode(".jxl", img_org, buff, param));
|
||||
EXPECT_TRUE(ret);
|
||||
Mat img_decoded;
|
||||
EXPECT_NO_THROW(img_decoded = imdecode(buff, IMREAD_UNCHANGED));
|
||||
EXPECT_FALSE(img_decoded.empty());
|
||||
|
||||
EXPECT_LE(cvtest::norm(img_org, img_decoded, NORM_INF), th);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
/**/,
|
||||
Imgcodecs_JpegXL_MatType,
|
||||
testing::Combine(
|
||||
testing::Values(
|
||||
CV_8UC1, CV_8UC3, CV_8UC4,
|
||||
CV_16UC1, CV_16UC3, CV_16UC4,
|
||||
CV_32FC1, CV_32FC3, CV_32FC4
|
||||
),
|
||||
testing::Values( // Distance
|
||||
0, // Lossless
|
||||
1, // Default
|
||||
3, // Recomended Lossy Max
|
||||
25 // Specification Max
|
||||
)
|
||||
) );
|
||||
|
||||
|
||||
typedef tuple<int, int> Effort_and_Decoding_speed;
|
||||
typedef testing::TestWithParam<Effort_and_Decoding_speed> Imgcodecs_JpegXL_Effort_DecodingSpeed;
|
||||
|
||||
TEST_P(Imgcodecs_JpegXL_Effort_DecodingSpeed, encode_decode)
|
||||
{
|
||||
const int effort = get<0>(GetParam());
|
||||
const int speed = get<1>(GetParam());
|
||||
|
||||
cv::Scalar col = cv::Scalar(124,76,42);
|
||||
// Jpeg XL is lossy compression.
|
||||
// There may be small differences in decoding results by environments.
|
||||
double th = 3; // = 255 / 100 (1%);
|
||||
|
||||
bool ret = false;
|
||||
vector<uchar> buff;
|
||||
Mat img_org(320, 480, CV_8UC3, col);
|
||||
vector<int> param;
|
||||
param.push_back(IMWRITE_JPEGXL_EFFORT);
|
||||
param.push_back(effort);
|
||||
param.push_back(IMWRITE_JPEGXL_DECODING_SPEED);
|
||||
param.push_back(speed);
|
||||
EXPECT_NO_THROW(ret = imencode(".jxl", img_org, buff, param));
|
||||
EXPECT_TRUE(ret);
|
||||
Mat img_decoded;
|
||||
EXPECT_NO_THROW(img_decoded = imdecode(buff, IMREAD_UNCHANGED));
|
||||
EXPECT_FALSE(img_decoded.empty());
|
||||
|
||||
EXPECT_LE(cvtest::norm(img_org, img_decoded, NORM_INF), th);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
/**/,
|
||||
Imgcodecs_JpegXL_Effort_DecodingSpeed,
|
||||
testing::Combine(
|
||||
testing::Values( // Effort
|
||||
1, // fastest
|
||||
7, // default
|
||||
9 // slowest
|
||||
),
|
||||
testing::Values( // Decoding Speed
|
||||
0, // default, slowest, and best quality/density
|
||||
2,
|
||||
4 // fastest, at the cost of some qulity/density
|
||||
)
|
||||
) );
|
||||
|
||||
TEST(Imgcodecs_JpegXL, encode_from_uncontinued_image)
|
||||
{
|
||||
cv::Mat src(100, 100, CV_8UC1, Scalar(40,50,10));
|
||||
cv::Mat roi = src(cv::Rect(10,20,30,50));
|
||||
EXPECT_FALSE(roi.isContinuous()); // uncontinued image
|
||||
|
||||
vector<uint8_t> buff;
|
||||
vector<int> param;
|
||||
bool ret = false;
|
||||
EXPECT_NO_THROW(ret = cv::imencode(".jxl", roi, buff, param));
|
||||
EXPECT_TRUE(ret);
|
||||
}
|
||||
|
||||
#endif // HAVE_JPEGXL
|
||||
|
||||
} // namespace
|
||||
} // namespace opencv_test
|
||||
@@ -157,6 +157,9 @@ const string exts[] = {
|
||||
#ifdef HAVE_JPEG
|
||||
"jpg",
|
||||
#endif
|
||||
#ifdef HAVE_JPEGXL
|
||||
"jxl",
|
||||
#endif
|
||||
#if (defined(HAVE_JASPER) && defined(OPENCV_IMGCODECS_ENABLE_JASPER_TESTS)) \
|
||||
|| defined(HAVE_OPENJPEG)
|
||||
"jp2",
|
||||
@@ -238,6 +241,8 @@ TEST_P(Imgcodecs_Image, read_write_BGR)
|
||||
double psnrThreshold = 100;
|
||||
if (ext == "jpg")
|
||||
psnrThreshold = 32;
|
||||
if (ext == "jxl")
|
||||
psnrThreshold = 30;
|
||||
#if defined(HAVE_JASPER)
|
||||
if (ext == "jp2")
|
||||
psnrThreshold = 95;
|
||||
@@ -268,6 +273,8 @@ TEST_P(Imgcodecs_Image, read_write_GRAYSCALE)
|
||||
double psnrThreshold = 100;
|
||||
if (ext == "jpg")
|
||||
psnrThreshold = 40;
|
||||
if (ext == "jxl")
|
||||
psnrThreshold = 40;
|
||||
#if defined(HAVE_JASPER)
|
||||
if (ext == "jp2")
|
||||
psnrThreshold = 70;
|
||||
|
||||
@@ -1,29 +1,16 @@
|
||||
// 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
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#ifdef HAVE_WEBP
|
||||
|
||||
TEST(Imgcodecs_WebP, encode_decode_lossless_webp)
|
||||
static void readFileBytes(const std::string& fname, std::vector<unsigned char>& buf)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
string filename = root + "../cv/shared/lena.png";
|
||||
cv::Mat img = cv::imread(filename);
|
||||
ASSERT_FALSE(img.empty());
|
||||
|
||||
string output = cv::tempfile(".webp");
|
||||
EXPECT_NO_THROW(cv::imwrite(output, img)); // lossless
|
||||
|
||||
cv::Mat img_webp = cv::imread(output);
|
||||
|
||||
std::vector<unsigned char> buf;
|
||||
|
||||
FILE * wfile = NULL;
|
||||
|
||||
wfile = fopen(output.c_str(), "rb");
|
||||
FILE * wfile = fopen(fname.c_str(), "rb");
|
||||
if (wfile != NULL)
|
||||
{
|
||||
fseek(wfile, 0, SEEK_END);
|
||||
@@ -39,12 +26,24 @@ TEST(Imgcodecs_WebP, encode_decode_lossless_webp)
|
||||
fclose(wfile);
|
||||
}
|
||||
|
||||
if (data_size != wfile_size)
|
||||
{
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
EXPECT_EQ(data_size, wfile_size);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_WebP, encode_decode_lossless_webp)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
string filename = root + "../cv/shared/lena.png";
|
||||
cv::Mat img = cv::imread(filename);
|
||||
ASSERT_FALSE(img.empty());
|
||||
|
||||
string output = cv::tempfile(".webp");
|
||||
EXPECT_NO_THROW(cv::imwrite(output, img)); // lossless
|
||||
|
||||
cv::Mat img_webp = cv::imread(output);
|
||||
|
||||
std::vector<unsigned char> buf;
|
||||
readFileBytes(output, buf);
|
||||
EXPECT_EQ(0, remove(output.c_str()));
|
||||
|
||||
cv::Mat decode = cv::imdecode(buf, IMREAD_COLOR);
|
||||
|
||||
@@ -12,6 +12,10 @@ ocv_add_dispatched_file(smooth SSE2 SSE4_1 AVX2)
|
||||
ocv_add_dispatched_file(sumpixels SSE2 AVX2 AVX512_SKX)
|
||||
ocv_define_module(imgproc opencv_core WRAP java objc python js)
|
||||
|
||||
if(OPENCV_CORE_EXCLUDE_C_API)
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE "OPENCV_EXCLUDE_C_API=1")
|
||||
endif()
|
||||
|
||||
if(HAVE_IPP)
|
||||
# OPENCV_IPP_ENABLE_ALL is defined in modules/core/CMakeList.txt
|
||||
OCV_OPTION(OPENCV_IPP_GAUSSIAN_BLUR "Enable IPP optimizations for GaussianBlur (+8Mb in binary size)" OPENCV_IPP_ENABLE_ALL)
|
||||
|
||||
@@ -2165,11 +2165,13 @@ Must fall between 0 and max_theta.
|
||||
@param max_theta For standard and multi-scale Hough transform, an upper bound for the angle.
|
||||
Must fall between min_theta and CV_PI. The actual maximum angle in the accumulator may be slightly
|
||||
less than max_theta, depending on the parameters min_theta and theta.
|
||||
@param use_edgeval True if you want to use weighted Hough transform.
|
||||
*/
|
||||
CV_EXPORTS_W void HoughLines( InputArray image, OutputArray lines,
|
||||
double rho, double theta, int threshold,
|
||||
double srn = 0, double stn = 0,
|
||||
double min_theta = 0, double max_theta = CV_PI );
|
||||
double min_theta = 0, double max_theta = CV_PI,
|
||||
bool use_edgeval = false );
|
||||
|
||||
/** @brief Finds line segments in a binary image using the probabilistic Hough transform.
|
||||
|
||||
@@ -4342,7 +4344,7 @@ CV_EXPORTS_W RotatedRect fitEllipseAMS( InputArray points );
|
||||
|
||||
The function calculates the ellipse that fits a set of 2D points.
|
||||
It returns the rotated rectangle in which the ellipse is inscribed.
|
||||
The Direct least square (Direct) method by @cite Fitzgibbon1999 is used.
|
||||
The Direct least square (Direct) method by @cite oy1998NumericallySD is used.
|
||||
|
||||
For an ellipse, this basis set is \f$ \chi= \left(x^2, x y, y^2, x, y, 1\right) \f$,
|
||||
which is a set of six free coefficients \f$ A^T=\left\{A_{\text{xx}},A_{\text{xy}},A_{\text{yy}},A_x,A_y,A_0\right\} \f$.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "opencv2/core/cvdef.h"
|
||||
#include "opencv2/core/cvstd.hpp"
|
||||
#include "opencv2/core/utility.hpp"
|
||||
#include "opencv2/core/hal/interface.h"
|
||||
|
||||
namespace cv { namespace hal {
|
||||
@@ -158,12 +159,14 @@ CV_EXPORTS void cvtGraytoBGR5x5(const uchar * src_data, size_t src_step,
|
||||
CV_EXPORTS void cvtBGRtoYUV(const uchar * src_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
int width, int height,
|
||||
int depth, int scn, bool swapBlue, bool isCbCr);
|
||||
int depth, int scn, bool swapBlue, bool isCbCr,
|
||||
AlgorithmHint hint = ALGO_HINT_DEFAULT);
|
||||
|
||||
CV_EXPORTS void cvtYUVtoBGR(const uchar * src_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
int width, int height,
|
||||
int depth, int dcn, bool swapBlue, bool isCbCr);
|
||||
int depth, int dcn, bool swapBlue, bool isCbCr,
|
||||
AlgorithmHint hint = ALGO_HINT_DEFAULT);
|
||||
|
||||
CV_EXPORTS void cvtBGRtoXYZ(const uchar * src_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
@@ -198,28 +201,33 @@ CV_EXPORTS void cvtLabtoBGR(const uchar * src_data, size_t src_step,
|
||||
CV_EXPORTS void cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
int dst_width, int dst_height,
|
||||
int dcn, bool swapBlue, int uIdx);
|
||||
int dcn, bool swapBlue, int uIdx,
|
||||
AlgorithmHint hint = ALGO_HINT_DEFAULT);
|
||||
|
||||
//! Separate Y and UV planes
|
||||
CV_EXPORTS void cvtTwoPlaneYUVtoBGR(const uchar * y_data, const uchar * uv_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
int dst_width, int dst_height,
|
||||
int dcn, bool swapBlue, int uIdx);
|
||||
int dcn, bool swapBlue, int uIdx,
|
||||
AlgorithmHint hint = ALGO_HINT_DEFAULT);
|
||||
|
||||
CV_EXPORTS void cvtTwoPlaneYUVtoBGR(const uchar * y_data, size_t y_step, const uchar * uv_data, size_t uv_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
int dst_width, int dst_height,
|
||||
int dcn, bool swapBlue, int uIdx);
|
||||
int dcn, bool swapBlue, int uIdx,
|
||||
AlgorithmHint hint = ALGO_HINT_DEFAULT);
|
||||
|
||||
CV_EXPORTS void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
int dst_width, int dst_height,
|
||||
int dcn, bool swapBlue, int uIdx);
|
||||
int dcn, bool swapBlue, int uIdx,
|
||||
AlgorithmHint hint = ALGO_HINT_DEFAULT);
|
||||
|
||||
CV_EXPORTS void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
int width, int height,
|
||||
int scn, bool swapBlue, int uIdx);
|
||||
int scn, bool swapBlue, int uIdx,
|
||||
AlgorithmHint hint = ALGO_HINT_DEFAULT);
|
||||
|
||||
//! Separate Y and UV planes
|
||||
CV_EXPORTS void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step,
|
||||
@@ -230,12 +238,14 @@ CV_EXPORTS void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step,
|
||||
CV_EXPORTS void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
int width, int height,
|
||||
int dcn, bool swapBlue, int uIdx, int ycn);
|
||||
int dcn, bool swapBlue, int uIdx, int ycn,
|
||||
AlgorithmHint hint = ALGO_HINT_DEFAULT);
|
||||
|
||||
CV_EXPORTS void cvtOnePlaneBGRtoYUV(const uchar * src_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
int width, int height,
|
||||
int scn, bool swapBlue, int uIdx, int ycn);
|
||||
int scn, bool swapBlue, int uIdx, int ycn,
|
||||
AlgorithmHint hint = ALGO_HINT_DEFAULT);
|
||||
|
||||
CV_EXPORTS void cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
|
||||
@@ -219,7 +219,7 @@ replication border mode.
|
||||
@see cv::warpAffine
|
||||
*/
|
||||
CVAPI(void) cvWarpAffine( const CvArr* src, CvArr* dst, const CvMat* map_matrix,
|
||||
int flags CV_DEFAULT(CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS),
|
||||
int flags CV_DEFAULT(+CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS),
|
||||
CvScalar fillval CV_DEFAULT(cvScalarAll(0)) );
|
||||
|
||||
/** @brief Computes affine transform matrix for mapping src[i] to dst[i] (i=0,1,2)
|
||||
@@ -239,7 +239,7 @@ CVAPI(CvMat*) cv2DRotationMatrix( CvPoint2D32f center, double angle,
|
||||
@see cv::warpPerspective
|
||||
*/
|
||||
CVAPI(void) cvWarpPerspective( const CvArr* src, CvArr* dst, const CvMat* map_matrix,
|
||||
int flags CV_DEFAULT(CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS),
|
||||
int flags CV_DEFAULT(+CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS),
|
||||
CvScalar fillval CV_DEFAULT(cvScalarAll(0)) );
|
||||
|
||||
/** @brief Computes perspective transform matrix for mapping src[i] to dst[i] (i=0,1,2,3)
|
||||
@@ -254,7 +254,7 @@ CVAPI(CvMat*) cvGetPerspectiveTransform( const CvPoint2D32f* src,
|
||||
*/
|
||||
CVAPI(void) cvRemap( const CvArr* src, CvArr* dst,
|
||||
const CvArr* mapx, const CvArr* mapy,
|
||||
int flags CV_DEFAULT(CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS),
|
||||
int flags CV_DEFAULT(+CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS),
|
||||
CvScalar fillval CV_DEFAULT(cvScalarAll(0)) );
|
||||
|
||||
/** @brief Converts mapx & mapy from floating-point to integer formats for cvRemap
|
||||
@@ -268,14 +268,14 @@ CVAPI(void) cvConvertMaps( const CvArr* mapx, const CvArr* mapy,
|
||||
*/
|
||||
CVAPI(void) cvLogPolar( const CvArr* src, CvArr* dst,
|
||||
CvPoint2D32f center, double M,
|
||||
int flags CV_DEFAULT(CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS));
|
||||
int flags CV_DEFAULT(+CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS));
|
||||
|
||||
/** Performs forward or inverse linear-polar image transform
|
||||
@see cv::warpPolar
|
||||
*/
|
||||
CVAPI(void) cvLinearPolar( const CvArr* src, CvArr* dst,
|
||||
CvPoint2D32f center, double maxRadius,
|
||||
int flags CV_DEFAULT(CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS));
|
||||
int flags CV_DEFAULT(+CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS));
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( pop )
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
*
|
||||
* @param targetPt The target point
|
||||
* @param[out] contour The list of pixels which contains optimal path between the source and the target points of the image. Type is CV_32SC2 (compatible with `std::vector<Point>`)
|
||||
* @param backward Flag to indicate reverse order of retrived pixels (use "true" value to fetch points from the target to the source point)
|
||||
* @param backward Flag to indicate reverse order of retrieved pixels (use "true" value to fetch points from the target to the source point)
|
||||
*/
|
||||
CV_WRAP void getContour(const Point& targetPt, OutputArray contour, bool backward = false) const;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user