Merge remote-tracking branch 'origin/3.4' into merge-3.4

pull/23827/head
Alexander Smorkalov 1 year ago
commit 004801f1c5
  1. 5
      apps/createsamples/utility.cpp
  2. 5
      modules/core/include/opencv2/core/optim.hpp
  3. 20
      modules/core/src/lpsolver.cpp
  4. 14
      modules/core/test/test_lpsolver.cpp
  5. 31
      modules/imgproc/src/distransform.cpp
  6. 42
      modules/imgproc/test/test_distancetransform.cpp
  7. 2
      modules/videoio/src/cap_ffmpeg_impl.hpp
  8. 17
      platforms/ios/cmake/Toolchains/common-ios-toolchain.cmake

@ -70,7 +70,7 @@ using namespace cv;
static int icvMkDir( const char* filename ) static int icvMkDir( const char* filename )
{ {
char path[PATH_MAX]; char path[PATH_MAX+1];
char* p; char* p;
int pos; int pos;
@ -83,7 +83,8 @@ static int icvMkDir( const char* filename )
mode = 0755; mode = 0755;
#endif /* _WIN32 */ #endif /* _WIN32 */
strcpy( path, filename ); path[0] = '\0';
strncat( path, filename, PATH_MAX );
p = path; p = path;
for( ; ; ) for( ; ; )

@ -256,6 +256,7 @@ public:
//! return codes for cv::solveLP() function //! return codes for cv::solveLP() function
enum SolveLPResult enum SolveLPResult
{ {
SOLVELP_LOST = -3, //!< problem is feasible, but solver lost solution due to floating-point arithmetic errors
SOLVELP_UNBOUNDED = -2, //!< problem is unbounded (target function can achieve arbitrary high values) SOLVELP_UNBOUNDED = -2, //!< problem is unbounded (target function can achieve arbitrary high values)
SOLVELP_UNFEASIBLE = -1, //!< problem is unfeasible (there are no points that satisfy all the constraints imposed) SOLVELP_UNFEASIBLE = -1, //!< problem is unfeasible (there are no points that satisfy all the constraints imposed)
SOLVELP_SINGLE = 0, //!< there is only one maximum for target function SOLVELP_SINGLE = 0, //!< there is only one maximum for target function
@ -291,8 +292,12 @@ in the latter case it is understood to correspond to \f$c^T\f$.
and the remaining to \f$A\f$. It should contain 32- or 64-bit floating point numbers. and the remaining to \f$A\f$. It should contain 32- or 64-bit floating point numbers.
@param z The solution will be returned here as a column-vector - it corresponds to \f$c\f$ in the @param z The solution will be returned here as a column-vector - it corresponds to \f$c\f$ in the
formulation above. It will contain 64-bit floating point numbers. formulation above. It will contain 64-bit floating point numbers.
@param constr_eps allowed numeric disparity for constraints
@return One of cv::SolveLPResult @return One of cv::SolveLPResult
*/ */
CV_EXPORTS_W int solveLP(InputArray Func, InputArray Constr, OutputArray z, double constr_eps);
/** @overload */
CV_EXPORTS_W int solveLP(InputArray Func, InputArray Constr, OutputArray z); CV_EXPORTS_W int solveLP(InputArray Func, InputArray Constr, OutputArray z);
//! @} //! @}

@ -90,7 +90,7 @@ static void swap_columns(Mat_<double>& A,int col1,int col2);
#define SWAP(type,a,b) {type tmp=(a);(a)=(b);(b)=tmp;} #define SWAP(type,a,b) {type tmp=(a);(a)=(b);(b)=tmp;}
//return codes:-2 (no_sol - unbdd),-1(no_sol - unfsbl), 0(single_sol), 1(multiple_sol=>least_l2_norm) //return codes:-2 (no_sol - unbdd),-1(no_sol - unfsbl), 0(single_sol), 1(multiple_sol=>least_l2_norm)
int solveLP(InputArray Func_, InputArray Constr_, OutputArray z_) int solveLP(InputArray Func_, InputArray Constr_, OutputArray z_, double constr_eps)
{ {
dprintf(("call to solveLP\n")); dprintf(("call to solveLP\n"));
@ -143,9 +143,25 @@ int solveLP(InputArray Func_, InputArray Constr_, OutputArray z_)
} }
z.copyTo(z_); z.copyTo(z_);
//check constraints feasibility
Mat prod = Constr(Rect(0, 0, Constr.cols - 1, Constr.rows)) * z;
Mat constr_check = Constr.col(Constr.cols - 1) - prod;
double min_value = 0.0;
minMaxIdx(constr_check, &min_value);
if (min_value < -constr_eps)
{
return SOLVELP_LOST;
}
return res; return res;
} }
int solveLP(InputArray Func, InputArray Constr, OutputArray z)
{
return solveLP(Func, Constr, z, 1e-12);
}
static int initialize_simplex(Mat_<double>& c, Mat_<double>& b,double& v,vector<int>& N,vector<int>& B,vector<unsigned int>& indexToRow){ static int initialize_simplex(Mat_<double>& c, Mat_<double>& b,double& v,vector<int>& N,vector<int>& B,vector<unsigned int>& indexToRow){
N.resize(c.cols); N.resize(c.cols);
N[0]=0; N[0]=0;
@ -255,7 +271,7 @@ static int initialize_simplex(Mat_<double>& c, Mat_<double>& b,double& v,vector<
static int inner_simplex(Mat_<double>& c, Mat_<double>& b,double& v,vector<int>& N,vector<int>& B,vector<unsigned int>& indexToRow){ static int inner_simplex(Mat_<double>& c, Mat_<double>& b,double& v,vector<int>& N,vector<int>& B,vector<unsigned int>& indexToRow){
for(;;){ for(;;){
static MatIterator_<double> pos_ptr; MatIterator_<double> pos_ptr;
int e=-1,pos_ctr=0,min_var=INT_MAX; int e=-1,pos_ctr=0,min_var=INT_MAX;
bool all_nonzero=true; bool all_nonzero=true;
for(pos_ptr=c.begin();pos_ptr!=c.end();pos_ptr++,pos_ctr++){ for(pos_ptr=c.begin();pos_ptr!=c.end();pos_ptr++,pos_ctr++){

@ -151,4 +151,18 @@ TEST(Core_LPSolver, issue_12337)
EXPECT_ANY_THROW(Mat1b z_8u; cv::solveLP(A, B, z_8u)); EXPECT_ANY_THROW(Mat1b z_8u; cv::solveLP(A, B, z_8u));
} }
// NOTE: Test parameters found experimentally to get numerically inaccurate result.
// The test behaviour may change after algorithm tuning and may removed.
TEST(Core_LPSolver, issue_12343)
{
Mat A = (cv::Mat_<double>(4, 1) << 3., 3., 3., 4.);
Mat B = (cv::Mat_<double>(4, 5) << 0., 1., 4., 4., 3.,
3., 1., 2., 2., 3.,
4., 4., 0., 1., 4.,
4., 0., 4., 1., 4.);
Mat z;
int result = cv::solveLP(A, B, z);
EXPECT_EQ(SOLVELP_LOST, result);
}
}} // namespace }} // namespace

@ -448,7 +448,7 @@ static void getDistanceTransformMask( int maskType, float *metrics )
struct DTColumnInvoker : ParallelLoopBody struct DTColumnInvoker : ParallelLoopBody
{ {
DTColumnInvoker( const Mat* _src, Mat* _dst, const int* _sat_tab, const float* _sqr_tab) DTColumnInvoker( const Mat* _src, Mat* _dst, const int* _sat_tab, const int* _sqr_tab)
{ {
src = _src; src = _src;
dst = _dst; dst = _dst;
@ -481,7 +481,7 @@ struct DTColumnInvoker : ParallelLoopBody
{ {
dist = dist + 1 - sat_tab[dist - d[j]]; dist = dist + 1 - sat_tab[dist - d[j]];
d[j] = dist; d[j] = dist;
dptr[0] = sqr_tab[dist]; dptr[0] = (float)sqr_tab[dist];
} }
} }
} }
@ -489,12 +489,12 @@ struct DTColumnInvoker : ParallelLoopBody
const Mat* src; const Mat* src;
Mat* dst; Mat* dst;
const int* sat_tab; const int* sat_tab;
const float* sqr_tab; const int* sqr_tab;
}; };
struct DTRowInvoker : ParallelLoopBody struct DTRowInvoker : ParallelLoopBody
{ {
DTRowInvoker( Mat* _dst, const float* _sqr_tab, const float* _inv_tab ) DTRowInvoker( Mat* _dst, const int* _sqr_tab, const float* _inv_tab )
{ {
dst = _dst; dst = _dst;
sqr_tab = _sqr_tab; sqr_tab = _sqr_tab;
@ -529,7 +529,7 @@ struct DTRowInvoker : ParallelLoopBody
for(;;k--) for(;;k--)
{ {
p = v[k]; p = v[k];
float s = (fq + sqr_tab[q] - d[p] - sqr_tab[p])*inv_tab[q - p]; float s = (fq - d[p] + (sqr_tab[q]-sqr_tab[p]))*inv_tab[q - p];
if( s > z[k] ) if( s > z[k] )
{ {
k++; k++;
@ -552,28 +552,28 @@ struct DTRowInvoker : ParallelLoopBody
} }
Mat* dst; Mat* dst;
const float* sqr_tab; const int* sqr_tab;
const float* inv_tab; const float* inv_tab;
}; };
static void static void
trueDistTrans( const Mat& src, Mat& dst ) trueDistTrans( const Mat& src, Mat& dst )
{ {
const float inf = 1e15f; const int inf = INT_MAX;
CV_Assert( src.size() == dst.size() ); CV_Assert( src.size() == dst.size() );
CV_Assert( src.type() == CV_8UC1 && dst.type() == CV_32FC1 ); CV_Assert( src.type() == CV_8UC1 && dst.type() == CV_32FC1 );
int i, m = src.rows, n = src.cols; int i, m = src.rows, n = src.cols;
cv::AutoBuffer<uchar> _buf(std::max(m*2*sizeof(float) + (m*3+1)*sizeof(int), n*2*sizeof(float))); cv::AutoBuffer<uchar> _buf(std::max(m*2*sizeof(int) + (m*3+1)*sizeof(int), n*2*sizeof(float)));
// stage 1: compute 1d distance transform of each column // stage 1: compute 1d distance transform of each column
float* sqr_tab = (float*)_buf.data(); int* sqr_tab = (int*)_buf.data();
int* sat_tab = cv::alignPtr((int*)(sqr_tab + m*2), sizeof(int)); int* sat_tab = cv::alignPtr((int*)(sqr_tab + m*2), sizeof(int));
int shift = m*2; int shift = m*2;
for( i = 0; i < m; i++ ) for( i = 0; i < m; i++ )
sqr_tab[i] = (float)(i*i); sqr_tab[i] = i*i;
for( i = m; i < m*2; i++ ) for( i = m; i < m*2; i++ )
sqr_tab[i] = inf; sqr_tab[i] = inf;
for( i = 0; i < shift; i++ ) for( i = 0; i < shift; i++ )
@ -584,13 +584,14 @@ trueDistTrans( const Mat& src, Mat& dst )
cv::parallel_for_(cv::Range(0, n), cv::DTColumnInvoker(&src, &dst, sat_tab, sqr_tab), src.total()/(double)(1<<16)); cv::parallel_for_(cv::Range(0, n), cv::DTColumnInvoker(&src, &dst, sat_tab, sqr_tab), src.total()/(double)(1<<16));
// stage 2: compute modified distance transform for each row // stage 2: compute modified distance transform for each row
float* inv_tab = sqr_tab + n; float* inv_tab = (float*)sqr_tab + n;
inv_tab[0] = sqr_tab[0] = 0.f; inv_tab[0] = 0.f;
sqr_tab[0] = 0;
for( i = 1; i < n; i++ ) for( i = 1; i < n; i++ )
{ {
inv_tab[i] = (float)(0.5/i); inv_tab[i] = (float)(0.5/i);
sqr_tab[i] = (float)(i*i); sqr_tab[i] = i*i;
} }
cv::parallel_for_(cv::Range(0, m), cv::DTRowInvoker(&dst, sqr_tab, inv_tab)); cv::parallel_for_(cv::Range(0, m), cv::DTRowInvoker(&dst, sqr_tab, inv_tab));
@ -750,7 +751,9 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
CV_IPP_CHECK() CV_IPP_CHECK()
{ {
#if IPP_DISABLE_PERF_TRUE_DIST_MT #if IPP_DISABLE_PERF_TRUE_DIST_MT
if(cv::getNumThreads()<=1 || (src.total()<(int)(1<<14))) // IPP uses floats, but 4097 cannot be squared into a float
if((cv::getNumThreads()<=1 || (src.total()<(int)(1<<14))) &&
src.rows < 4097 && src.cols < 4097)
#endif #endif
{ {
IppStatus status; IppStatus status;

@ -302,4 +302,46 @@ BIGDATA_TEST(Imgproc_DistanceTransform, large_image_12218)
EXPECT_EQ(nz, (size.height*size.width / 2)); EXPECT_EQ(nz, (size.height*size.width / 2));
} }
TEST(Imgproc_DistanceTransform, wide_image_22732)
{
Mat src = Mat::zeros(1, 4099, CV_8U); // 4099 or larger used to be bad
Mat dist(src.rows, src.cols, CV_32F);
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE, CV_32F);
int nz = countNonZero(dist);
EXPECT_EQ(nz, 0);
}
TEST(Imgproc_DistanceTransform, large_square_22732)
{
Mat src = Mat::zeros(8000, 8005, CV_8U), dist;
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE, CV_32F);
int nz = countNonZero(dist);
EXPECT_EQ(dist.size(), src.size());
EXPECT_EQ(dist.type(), CV_32F);
EXPECT_EQ(nz, 0);
Point p0(src.cols-1, src.rows-1);
src.setTo(1);
src.at<uchar>(p0) = 0;
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE, CV_32F);
EXPECT_EQ(dist.size(), src.size());
EXPECT_EQ(dist.type(), CV_32F);
bool first = true;
int nerrs = 0;
for (int y = 0; y < dist.rows; y++)
for (int x = 0; x < dist.cols; x++) {
float d = dist.at<float>(y, x);
double dx = (double)(x - p0.x), dy = (double)(y - p0.y);
float d0 = (float)sqrt(dx*dx + dy*dy);
if (std::abs(d0 - d) > 1) {
if (first) {
printf("y=%d, x=%d. dist_ref=%.2f, dist=%.2f\n", y, x, d0, d);
first = false;
}
nerrs++;
}
}
EXPECT_EQ(0, nerrs) << "reference distance map is different from computed one at " << nerrs << " pixels\n";
}
}} // namespace }} // namespace

@ -1847,7 +1847,7 @@ int64_t CvCapture_FFMPEG::get_bitrate() const
double CvCapture_FFMPEG::get_fps() const double CvCapture_FFMPEG::get_fps() const
{ {
#if 0 && LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 1, 100) && LIBAVFORMAT_VERSION_MICRO >= 100 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 1, 100) && LIBAVFORMAT_VERSION_MICRO >= 100
double fps = r2d(av_guess_frame_rate(ic, ic->streams[video_stream], NULL)); double fps = r2d(av_guess_frame_rate(ic, ic->streams[video_stream], NULL));
#else #else
double fps = r2d(ic->streams[video_stream]->avg_frame_rate); double fps = r2d(ic->streams[video_stream]->avg_frame_rate);

@ -101,8 +101,17 @@ if(NOT DEFINED IPHONEOS_DEPLOYMENT_TARGET AND NOT MAC_CATALYST)
endif() endif()
if(NOT __IN_TRY_COMPILE) if(NOT __IN_TRY_COMPILE)
set(_xcodebuild_wrapper "${CMAKE_BINARY_DIR}/xcodebuild_wrapper") set(_xcodebuild_wrapper "")
if(NOT EXISTS "${_xcodebuild_wrapper}") if(NOT (CMAKE_VERSION VERSION_LESS "3.25.1")) # >= 3.25.1
# no workaround is required (#23156)
elseif(NOT (CMAKE_VERSION VERSION_LESS "3.25.0")) # >= 3.25.0 < 3.25.1
if(NOT OPENCV_SKIP_MESSAGE_ISSUE_23156)
message(FATAL_ERROR "OpenCV: Please upgrade CMake to 3.25.1+. Current CMake version is ${CMAKE_VERSION}. Details: https://github.com/opencv/opencv/issues/23156")
endif()
else() # < 3.25.0, apply workaround from #13912
set(_xcodebuild_wrapper "${CMAKE_BINARY_DIR}/xcodebuild_wrapper")
endif()
if(_xcodebuild_wrapper AND NOT EXISTS "${_xcodebuild_wrapper}")
set(_xcodebuild_wrapper_tmp "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/xcodebuild_wrapper") set(_xcodebuild_wrapper_tmp "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/xcodebuild_wrapper")
if(NOT DEFINED CMAKE_MAKE_PROGRAM) # empty since CMake 3.10 if(NOT DEFINED CMAKE_MAKE_PROGRAM) # empty since CMake 3.10
find_program(XCODEBUILD_PATH "xcodebuild") find_program(XCODEBUILD_PATH "xcodebuild")
@ -122,7 +131,9 @@ if(NOT __IN_TRY_COMPILE)
configure_file("${CMAKE_CURRENT_LIST_DIR}/xcodebuild_wrapper.in" "${_xcodebuild_wrapper_tmp}" @ONLY) configure_file("${CMAKE_CURRENT_LIST_DIR}/xcodebuild_wrapper.in" "${_xcodebuild_wrapper_tmp}" @ONLY)
file(COPY "${_xcodebuild_wrapper_tmp}" DESTINATION ${CMAKE_BINARY_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) file(COPY "${_xcodebuild_wrapper_tmp}" DESTINATION ${CMAKE_BINARY_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endif() endif()
set(CMAKE_MAKE_PROGRAM "${_xcodebuild_wrapper}" CACHE INTERNAL "" FORCE) if(_xcodebuild_wrapper)
set(CMAKE_MAKE_PROGRAM "${_xcodebuild_wrapper}" CACHE INTERNAL "" FORCE)
endif()
endif() endif()
# Standard settings # Standard settings

Loading…
Cancel
Save