mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Merge remote-tracking branch 'refs/remotes/opencv/master' into FileStorageBase64DocsTests
# Conflicts: # modules/core/test/test_io.cpp
This commit is contained in:
+464
-251
@@ -59,23 +59,27 @@
|
||||
|
||||
\************************************************************************************/
|
||||
|
||||
/************************************************************************************\
|
||||
This version adds a new and improved variant of chessboard corner detection
|
||||
that works better in poor lighting condition. It is based on work from
|
||||
Oliver Schreer and Stefano Masneri. This method works faster than the previous
|
||||
one and reverts back to the older method in case no chessboard detection is
|
||||
possible. Overall performance improves also because now the method avoids
|
||||
performing the same computation multiple times when not necessary.
|
||||
|
||||
\************************************************************************************/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/calib3d/calib3d_c.h"
|
||||
#include "circlesgrid.hpp"
|
||||
#include <stdarg.h>
|
||||
#include <vector>
|
||||
|
||||
//#define ENABLE_TRIM_COL_ROW
|
||||
|
||||
//#define DEBUG_CHESSBOARD
|
||||
#ifdef DEBUG_CHESSBOARD
|
||||
# include "opencv2/opencv_modules.hpp"
|
||||
# ifdef HAVE_OPENCV_HIGHGUI
|
||||
# include "opencv2/highgui.hpp"
|
||||
# else
|
||||
# undef DEBUG_CHESSBOARD
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_CHESSBOARD
|
||||
static int PRINTF( const char* fmt, ... )
|
||||
{
|
||||
@@ -191,38 +195,204 @@ static void icvRemoveQuadFromGroup(CvCBQuad **quads, int count, CvCBQuad *q0);
|
||||
|
||||
static int icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size );
|
||||
|
||||
#if 0
|
||||
static void
|
||||
icvCalcAffineTranf2D32f(CvPoint2D32f* pts1, CvPoint2D32f* pts2, int count, CvMat* affine_trans)
|
||||
int cvCheckChessboardBinary(IplImage* src, CvSize size);
|
||||
|
||||
/***************************************************************************************************/
|
||||
//COMPUTE INTENSITY HISTOGRAM OF INPUT IMAGE
|
||||
static int icvGetIntensityHistogram( unsigned char* pucImage, int iSizeCols, int iSizeRows, std::vector<int>& piHist );
|
||||
//SMOOTH HISTOGRAM USING WINDOW OF SIZE 2*iWidth+1
|
||||
static int icvSmoothHistogram( const std::vector<int>& piHist, std::vector<int>& piHistSmooth, int iWidth );
|
||||
//COMPUTE FAST HISTOGRAM GRADIENT
|
||||
static int icvGradientOfHistogram( const std::vector<int>& piHist, std::vector<int>& piHistGrad );
|
||||
//PERFORM SMART IMAGE THRESHOLDING BASED ON ANALYSIS OF INTENSTY HISTOGRAM
|
||||
static bool icvBinarizationHistogramBased( unsigned char* pucImg, int iCols, int iRows );
|
||||
/***************************************************************************************************/
|
||||
int icvGetIntensityHistogram( unsigned char* pucImage, int iSizeCols, int iSizeRows, std::vector<int>& piHist )
|
||||
{
|
||||
int i, j;
|
||||
int real_count = 0;
|
||||
for( j = 0; j < count; j++ )
|
||||
int iVal;
|
||||
|
||||
// sum up all pixel in row direction and divide by number of columns
|
||||
for ( int j=0; j<iSizeRows; j++ )
|
||||
{
|
||||
for ( int i=0; i<iSizeCols; i++ )
|
||||
{
|
||||
if( pts1[j].x >= 0 ) real_count++;
|
||||
iVal = (int)pucImage[j*iSizeCols+i];
|
||||
piHist[iVal]++;
|
||||
}
|
||||
if(real_count < 3) return;
|
||||
cv::Ptr<CvMat> xy = cvCreateMat( 2*real_count, 6, CV_32FC1 );
|
||||
cv::Ptr<CvMat> uv = cvCreateMat( 2*real_count, 1, CV_32FC1 );
|
||||
//estimate affine transfromation
|
||||
for( i = 0, j = 0; j < count; j++ )
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/***************************************************************************************************/
|
||||
int icvSmoothHistogram( const std::vector<int>& piHist, std::vector<int>& piHistSmooth, int iWidth )
|
||||
{
|
||||
int iIdx;
|
||||
for ( int i=0; i<256; i++)
|
||||
{
|
||||
int iSmooth = 0;
|
||||
for ( int ii=-iWidth; ii<=iWidth; ii++)
|
||||
{
|
||||
if( pts1[j].x >= 0 )
|
||||
{
|
||||
CV_MAT_ELEM( *xy, float, i*2+1, 2 ) = CV_MAT_ELEM( *xy, float, i*2, 0 ) = pts2[j].x;
|
||||
CV_MAT_ELEM( *xy, float, i*2+1, 3 ) = CV_MAT_ELEM( *xy, float, i*2, 1 ) = pts2[j].y;
|
||||
CV_MAT_ELEM( *xy, float, i*2, 2 ) = CV_MAT_ELEM( *xy, float, i*2, 3 ) = CV_MAT_ELEM( *xy, float, i*2, 5 ) = \
|
||||
CV_MAT_ELEM( *xy, float, i*2+1, 0 ) = CV_MAT_ELEM( *xy, float, i*2+1, 1 ) = CV_MAT_ELEM( *xy, float, i*2+1, 4 ) = 0;
|
||||
CV_MAT_ELEM( *xy, float, i*2, 4 ) = CV_MAT_ELEM( *xy, float, i*2+1, 5 ) = 1;
|
||||
CV_MAT_ELEM( *uv, float, i*2, 0 ) = pts1[j].x;
|
||||
CV_MAT_ELEM( *uv, float, i*2+1, 0 ) = pts1[j].y;
|
||||
i++;
|
||||
}
|
||||
iIdx = i+ii;
|
||||
if (iIdx > 0 && iIdx < 256)
|
||||
{
|
||||
iSmooth += piHist[iIdx];
|
||||
}
|
||||
}
|
||||
piHistSmooth[i] = iSmooth/(2*iWidth+1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/***************************************************************************************************/
|
||||
int icvGradientOfHistogram( const std::vector<int>& piHist, std::vector<int>& piHistGrad )
|
||||
{
|
||||
piHistGrad[0] = 0;
|
||||
for ( int i=1; i<255; i++)
|
||||
{
|
||||
piHistGrad[i] = piHist[i-1] - piHist[i+1];
|
||||
if ( abs(piHistGrad[i]) < 100 )
|
||||
{
|
||||
if ( piHistGrad[i-1] == 0)
|
||||
piHistGrad[i] = -100;
|
||||
else
|
||||
piHistGrad[i] = piHistGrad[i-1];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/***************************************************************************************************/
|
||||
bool icvBinarizationHistogramBased( unsigned char* pucImg, int iCols, int iRows )
|
||||
{
|
||||
int iMaxPix = iCols*iRows;
|
||||
int iMaxPix1 = iMaxPix/100;
|
||||
const int iNumBins = 256;
|
||||
std::vector<int> piHistIntensity(iNumBins, 0);
|
||||
std::vector<int> piHistSmooth(iNumBins, 0);
|
||||
std::vector<int> piHistGrad(iNumBins, 0);
|
||||
std::vector<int> piAccumSum(iNumBins, 0);
|
||||
std::vector<int> piMaxPos(20, 0);
|
||||
int iThresh = 0;
|
||||
int iIdx;
|
||||
int iWidth = 1;
|
||||
|
||||
icvGetIntensityHistogram( pucImg, iCols, iRows, piHistIntensity );
|
||||
|
||||
// get accumulated sum starting from bright
|
||||
piAccumSum[iNumBins-1] = piHistIntensity[iNumBins-1];
|
||||
for ( int i=iNumBins-2; i>=0; i-- )
|
||||
{
|
||||
piAccumSum[i] = piHistIntensity[i] + piAccumSum[i+1];
|
||||
}
|
||||
|
||||
// first smooth the distribution
|
||||
icvSmoothHistogram( piHistIntensity, piHistSmooth, iWidth );
|
||||
|
||||
// compute gradient
|
||||
icvGradientOfHistogram( piHistSmooth, piHistGrad );
|
||||
|
||||
// check for zeros
|
||||
int iCntMaxima = 0;
|
||||
for ( int i=iNumBins-2; (i>2) && (iCntMaxima<20); i--)
|
||||
{
|
||||
if ( (piHistGrad[i-1] < 0) && (piHistGrad[i] > 0) )
|
||||
{
|
||||
piMaxPos[iCntMaxima] = i;
|
||||
iCntMaxima++;
|
||||
}
|
||||
}
|
||||
|
||||
iIdx = 0;
|
||||
int iSumAroundMax = 0;
|
||||
for ( int i=0; i<iCntMaxima; i++ )
|
||||
{
|
||||
iIdx = piMaxPos[i];
|
||||
iSumAroundMax = piHistSmooth[iIdx-1] + piHistSmooth[iIdx] + piHistSmooth[iIdx+1];
|
||||
if ( iSumAroundMax < iMaxPix1 && iIdx < 64 )
|
||||
{
|
||||
for ( int j=i; j<iCntMaxima-1; j++ )
|
||||
{
|
||||
piMaxPos[j] = piMaxPos[j+1];
|
||||
}
|
||||
iCntMaxima--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if ( iCntMaxima == 1)
|
||||
{
|
||||
iThresh = piMaxPos[0]/2;
|
||||
}
|
||||
else if ( iCntMaxima == 2)
|
||||
{
|
||||
iThresh = (piMaxPos[0] + piMaxPos[1])/2;
|
||||
}
|
||||
else // iCntMaxima >= 3
|
||||
{
|
||||
// CHECKING THRESHOLD FOR WHITE
|
||||
int iIdxAccSum = 0, iAccum = 0;
|
||||
for (int i=iNumBins-1; i>0; i--)
|
||||
{
|
||||
iAccum += piHistIntensity[i];
|
||||
// iMaxPix/18 is about 5,5%, minimum required number of pixels required for white part of chessboard
|
||||
if ( iAccum > (iMaxPix/18) )
|
||||
{
|
||||
iIdxAccSum = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cvSolve( xy, uv, affine_trans, CV_SVD );
|
||||
int iIdxBGMax = 0;
|
||||
int iBrightMax = piMaxPos[0];
|
||||
// printf("iBrightMax = %d\n", iBrightMax);
|
||||
for ( int n=0; n<iCntMaxima-1; n++)
|
||||
{
|
||||
iIdxBGMax = n+1;
|
||||
if ( piMaxPos[n] < iIdxAccSum )
|
||||
{
|
||||
break;
|
||||
}
|
||||
iBrightMax = piMaxPos[n];
|
||||
}
|
||||
|
||||
// CHECKING THRESHOLD FOR BLACK
|
||||
int iMaxVal = piHistIntensity[piMaxPos[iIdxBGMax]];
|
||||
|
||||
//IF TOO CLOSE TO 255, jump to next maximum
|
||||
if ( piMaxPos[iIdxBGMax] >= 250 && iIdxBGMax < iCntMaxima )
|
||||
{
|
||||
iIdxBGMax++;
|
||||
iMaxVal = piHistIntensity[piMaxPos[iIdxBGMax]];
|
||||
}
|
||||
|
||||
for ( int n=iIdxBGMax + 1; n<iCntMaxima; n++)
|
||||
{
|
||||
if ( piHistIntensity[piMaxPos[n]] >= iMaxVal )
|
||||
{
|
||||
iMaxVal = piHistIntensity[piMaxPos[n]];
|
||||
iIdxBGMax = n;
|
||||
}
|
||||
}
|
||||
|
||||
//SETTING THRESHOLD FOR BINARIZATION
|
||||
int iDist2 = (iBrightMax - piMaxPos[iIdxBGMax])/2;
|
||||
iThresh = iBrightMax - iDist2;
|
||||
PRINTF("THRESHOLD SELECTED = %d, BRIGHTMAX = %d, DARKMAX = %d\n", iThresh, iBrightMax, piMaxPos[iIdxBGMax]);
|
||||
}
|
||||
|
||||
|
||||
if ( iThresh > 0 )
|
||||
{
|
||||
for ( int jj=0; jj<iRows; jj++)
|
||||
{
|
||||
for ( int ii=0; ii<iCols; ii++)
|
||||
{
|
||||
if ( pucImg[jj*iCols+ii]< iThresh )
|
||||
pucImg[jj*iCols+ii] = 0;
|
||||
else
|
||||
pucImg[jj*iCols+ii] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
CV_IMPL
|
||||
int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
|
||||
@@ -232,6 +402,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
|
||||
int found = 0;
|
||||
CvCBQuad *quads = 0, **quad_group = 0;
|
||||
CvCBCorner *corners = 0, **corner_group = 0;
|
||||
IplImage* cImgSeg = 0;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -239,14 +410,14 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
|
||||
const int min_dilations = 0;
|
||||
const int max_dilations = 7;
|
||||
cv::Ptr<CvMat> norm_img, thresh_img;
|
||||
#ifdef DEBUG_CHESSBOARD
|
||||
cv::Ptr<IplImage> dbg_img;
|
||||
cv::Ptr<IplImage> dbg1_img;
|
||||
cv::Ptr<IplImage> dbg2_img;
|
||||
#endif
|
||||
cv::Ptr<CvMemStorage> storage;
|
||||
|
||||
CvMat stub, *img = (CvMat*)arr;
|
||||
cImgSeg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1 );
|
||||
memcpy( cImgSeg->imageData, cvPtr1D( img, 0), img->rows*img->cols );
|
||||
|
||||
CvMat stub2, *thresh_img_new;
|
||||
thresh_img_new = cvGetMat( cImgSeg, &stub2, 0, 0 );
|
||||
|
||||
int expected_corners_num = (pattern_size.width/2+1)*(pattern_size.height/2+1);
|
||||
|
||||
@@ -255,7 +426,6 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
|
||||
if( out_corner_count )
|
||||
*out_corner_count = 0;
|
||||
|
||||
IplImage _img;
|
||||
int quad_count = 0, group_idx = 0, dilations = 0;
|
||||
|
||||
img = cvGetMat( img, &stub );
|
||||
@@ -273,12 +443,6 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
|
||||
storage.reset(cvCreateMemStorage(0));
|
||||
thresh_img.reset(cvCreateMat( img->rows, img->cols, CV_8UC1 ));
|
||||
|
||||
#ifdef DEBUG_CHESSBOARD
|
||||
dbg_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
|
||||
dbg1_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
|
||||
dbg2_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
|
||||
#endif
|
||||
|
||||
if( CV_MAT_CN(img->type) != 1 || (flags & CV_CALIB_CB_NORMALIZE_IMAGE) )
|
||||
{
|
||||
// equalize the input image histogram -
|
||||
@@ -300,11 +464,19 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
|
||||
|
||||
if( flags & CV_CALIB_CB_FAST_CHECK)
|
||||
{
|
||||
cvGetImage(img, &_img);
|
||||
int check_chessboard_result = cvCheckChessboard(&_img, pattern_size);
|
||||
if(check_chessboard_result <= 0)
|
||||
//perform new method for checking chessboard using a binary image.
|
||||
//image is binarised using a threshold dependent on the image histogram
|
||||
icvBinarizationHistogramBased( (unsigned char*) cImgSeg->imageData, cImgSeg->width, cImgSeg->height );
|
||||
int check_chessboard_result = cvCheckChessboardBinary(cImgSeg, pattern_size);
|
||||
if(check_chessboard_result <= 0) //fall back to the old method
|
||||
{
|
||||
return 0;
|
||||
IplImage _img;
|
||||
cvGetImage(img, &_img);
|
||||
check_chessboard_result = cvCheckChessboard(&_img, pattern_size);
|
||||
if(check_chessboard_result <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,201 +484,238 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
|
||||
// This is necessary because some squares simply do not separate properly with a single dilation. However,
|
||||
// we want to use the minimum number of dilations possible since dilations cause the squares to become smaller,
|
||||
// making it difficult to detect smaller squares.
|
||||
for( k = 0; k < 6; k++ )
|
||||
for( dilations = min_dilations; dilations <= max_dilations; dilations++ )
|
||||
{
|
||||
if (found)
|
||||
break; // already found it
|
||||
|
||||
cvFree(&quads);
|
||||
cvFree(&corners);
|
||||
|
||||
int max_quad_buf_size = 0;
|
||||
|
||||
//USE BINARY IMAGE COMPUTED USING icvBinarizationHistogramBased METHOD
|
||||
cvDilate( thresh_img_new, thresh_img_new, 0, 1 );
|
||||
|
||||
// So we can find rectangles that go to the edge, we draw a white line around the image edge.
|
||||
// Otherwise FindContours will miss those clipped rectangle contours.
|
||||
// The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()...
|
||||
cvRectangle( thresh_img_new, cvPoint(0,0), cvPoint(thresh_img_new->cols-1, thresh_img_new->rows-1), CV_RGB(255,255,255), 3, 8);
|
||||
quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img_new, flags, &max_quad_buf_size );
|
||||
PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num);
|
||||
|
||||
if( quad_count <= 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find quad's neighbors
|
||||
icvFindQuadNeighbors( quads, quad_count );
|
||||
|
||||
// allocate extra for adding in icvOrderFoundQuads
|
||||
cvFree(&quad_group);
|
||||
cvFree(&corner_group);
|
||||
quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size);
|
||||
corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 );
|
||||
|
||||
for( group_idx = 0; ; group_idx++ )
|
||||
{
|
||||
int count = 0;
|
||||
count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage );
|
||||
|
||||
int icount = count;
|
||||
if( count == 0 )
|
||||
break;
|
||||
|
||||
// order the quad corners globally
|
||||
// maybe delete or add some
|
||||
PRINTF("Starting ordering of inner quads\n");
|
||||
count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, pattern_size, max_quad_buf_size, storage );
|
||||
PRINTF("Orig count: %d After ordering: %d\n", icount, count);
|
||||
|
||||
if (count == 0)
|
||||
continue; // haven't found inner quads
|
||||
|
||||
// If count is more than it should be, this will remove those quads
|
||||
// which cause maximum deviation from a nice square pattern.
|
||||
count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size );
|
||||
PRINTF("Connected group: %d orig count: %d cleaned: %d\n", group_idx, icount, count);
|
||||
|
||||
count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size );
|
||||
PRINTF("Connected group: %d count: %d cleaned: %d\n", group_idx, icount, count);
|
||||
|
||||
int n = count > 0 ? pattern_size.width * pattern_size.height : -count;
|
||||
n = MIN( n, pattern_size.width * pattern_size.height );
|
||||
float sum_dist = 0;
|
||||
int total = 0;
|
||||
|
||||
for(int i = 0; i < n; i++ )
|
||||
{
|
||||
int ni = 0;
|
||||
float avgi = corner_group[i]->meanDist(&ni);
|
||||
sum_dist += avgi*ni;
|
||||
total += ni;
|
||||
}
|
||||
prev_sqr_size = cvRound(sum_dist/MAX(total, 1));
|
||||
|
||||
if( count > 0 || (out_corner_count && -count > *out_corner_count) )
|
||||
{
|
||||
// copy corners to output array
|
||||
for(int i = 0; i < n; i++ )
|
||||
out_corners[i] = corner_group[i]->pt;
|
||||
|
||||
if( out_corner_count )
|
||||
*out_corner_count = n;
|
||||
|
||||
if( count == pattern_size.width*pattern_size.height &&
|
||||
icvCheckBoardMonotony( out_corners, pattern_size ))
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}//dilations
|
||||
|
||||
PRINTF("Chessboard detection result 0: %d\n", found);
|
||||
|
||||
// revert to old, slower, method if detection failed
|
||||
if (!found)
|
||||
{
|
||||
PRINTF("Fallback to old algorithm\n");
|
||||
// empiric threshold level
|
||||
// thresholding performed here and not inside the cycle to save processing time
|
||||
int thresh_level;
|
||||
if ( !(flags & CV_CALIB_CB_ADAPTIVE_THRESH) )
|
||||
{
|
||||
double mean = cvAvg( img ).val[0];
|
||||
thresh_level = cvRound( mean - 10 );
|
||||
thresh_level = MAX( thresh_level, 10 );
|
||||
cvThreshold( img, thresh_img, thresh_level, 255, CV_THRESH_BINARY );
|
||||
}
|
||||
for( k = 0; k < 6; k++ )
|
||||
{
|
||||
int max_quad_buf_size = 0;
|
||||
for( dilations = min_dilations; dilations <= max_dilations; dilations++ )
|
||||
{
|
||||
if (found)
|
||||
break; // already found it
|
||||
if (found)
|
||||
break; // already found it
|
||||
|
||||
cvFree(&quads);
|
||||
cvFree(&corners);
|
||||
cvFree(&quads);
|
||||
cvFree(&corners);
|
||||
|
||||
/*if( k == 1 )
|
||||
// convert the input grayscale image to binary (black-n-white)
|
||||
if( flags & CV_CALIB_CB_ADAPTIVE_THRESH )
|
||||
{
|
||||
int block_size = cvRound(prev_sqr_size == 0 ?
|
||||
MIN(img->cols,img->rows)*(k%2 == 0 ? 0.2 : 0.1): prev_sqr_size*2)|1;
|
||||
|
||||
// convert to binary
|
||||
cvAdaptiveThreshold( img, thresh_img, 255,
|
||||
CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, block_size, (k/2)*5 );
|
||||
if (dilations > 0)
|
||||
cvDilate( thresh_img, thresh_img, 0, dilations-1 );
|
||||
}
|
||||
//if flag CV_CALIB_CB_ADAPTIVE_THRESH is not set it doesn't make sense
|
||||
//to iterate over k
|
||||
else
|
||||
{
|
||||
k = 6;
|
||||
cvDilate( thresh_img, thresh_img, 0, 1 );
|
||||
}
|
||||
|
||||
// So we can find rectangles that go to the edge, we draw a white line around the image edge.
|
||||
// Otherwise FindContours will miss those clipped rectangle contours.
|
||||
// The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()...
|
||||
cvRectangle( thresh_img, cvPoint(0,0), cvPoint(thresh_img->cols-1,
|
||||
thresh_img->rows-1), CV_RGB(255,255,255), 3, 8);
|
||||
|
||||
quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags, &max_quad_buf_size);
|
||||
PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num);
|
||||
|
||||
if( quad_count <= 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find quad's neighbors
|
||||
icvFindQuadNeighbors( quads, quad_count );
|
||||
|
||||
// allocate extra for adding in icvOrderFoundQuads
|
||||
cvFree(&quad_group);
|
||||
cvFree(&corner_group);
|
||||
quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size);
|
||||
corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 );
|
||||
|
||||
for( group_idx = 0; ; group_idx++ )
|
||||
{
|
||||
int count = 0;
|
||||
count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage );
|
||||
|
||||
int icount = count;
|
||||
if( count == 0 )
|
||||
break;
|
||||
|
||||
// order the quad corners globally
|
||||
// maybe delete or add some
|
||||
PRINTF("Starting ordering of inner quads\n");
|
||||
count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, pattern_size, max_quad_buf_size, storage );
|
||||
|
||||
PRINTF("Orig count: %d After ordering: %d\n", icount, count);
|
||||
|
||||
if (count == 0)
|
||||
continue; // haven't found inner quads
|
||||
|
||||
|
||||
// If count is more than it should be, this will remove those quads
|
||||
// which cause maximum deviation from a nice square pattern.
|
||||
count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size );
|
||||
PRINTF("Connected group: %d orig count: %d cleaned: %d\n", group_idx, icount, count);
|
||||
|
||||
count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size );
|
||||
PRINTF("Connected group: %d count: %d cleaned: %d\n", group_idx, icount, count);
|
||||
|
||||
int n = count > 0 ? pattern_size.width * pattern_size.height : -count;
|
||||
n = MIN( n, pattern_size.width * pattern_size.height );
|
||||
float sum_dist = 0;
|
||||
int total = 0;
|
||||
|
||||
for(int i = 0; i < n; i++ )
|
||||
{
|
||||
//Pattern was not found using binarization
|
||||
// Run multi-level quads extraction
|
||||
// In case one-level binarization did not give enough number of quads
|
||||
CV_CALL( quad_count = icvGenerateQuadsEx( &quads, &corners, storage, img, thresh_img, dilations, flags ));
|
||||
PRINTF("EX quad count: %d/%d\n", quad_count, expected_corners_num);
|
||||
int ni = 0;
|
||||
float avgi = corner_group[i]->meanDist(&ni);
|
||||
sum_dist += avgi*ni;
|
||||
total += ni;
|
||||
}
|
||||
else*/
|
||||
prev_sqr_size = cvRound(sum_dist/MAX(total, 1));
|
||||
|
||||
if( count > 0 || (out_corner_count && -count > *out_corner_count) )
|
||||
{
|
||||
// convert the input grayscale image to binary (black-n-white)
|
||||
if( flags & CV_CALIB_CB_ADAPTIVE_THRESH )
|
||||
{
|
||||
int block_size = cvRound(prev_sqr_size == 0 ?
|
||||
MIN(img->cols,img->rows)*(k%2 == 0 ? 0.2 : 0.1): prev_sqr_size*2)|1;
|
||||
// copy corners to output array
|
||||
for(int i = 0; i < n; i++ )
|
||||
out_corners[i] = corner_group[i]->pt;
|
||||
|
||||
// convert to binary
|
||||
cvAdaptiveThreshold( img, thresh_img, 255,
|
||||
CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, block_size, (k/2)*5 );
|
||||
if (dilations > 0)
|
||||
cvDilate( thresh_img, thresh_img, 0, dilations-1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make dilation before the thresholding.
|
||||
// It splits chessboard corners
|
||||
//cvDilate( img, thresh_img, 0, 1 );
|
||||
if( out_corner_count )
|
||||
*out_corner_count = n;
|
||||
|
||||
// empiric threshold level
|
||||
double mean = cvAvg( img ).val[0];
|
||||
int thresh_level = cvRound( mean - 10 );
|
||||
thresh_level = MAX( thresh_level, 10 );
|
||||
|
||||
cvThreshold( img, thresh_img, thresh_level, 255, CV_THRESH_BINARY );
|
||||
cvDilate( thresh_img, thresh_img, 0, dilations );
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CHESSBOARD
|
||||
cvCvtColor(thresh_img,dbg_img,CV_GRAY2BGR);
|
||||
#endif
|
||||
|
||||
// So we can find rectangles that go to the edge, we draw a white line around the image edge.
|
||||
// Otherwise FindContours will miss those clipped rectangle contours.
|
||||
// The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()...
|
||||
cvRectangle( thresh_img, cvPoint(0,0), cvPoint(thresh_img->cols-1,
|
||||
thresh_img->rows-1), CV_RGB(255,255,255), 3, 8);
|
||||
|
||||
quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags, &max_quad_buf_size);
|
||||
|
||||
PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_CHESSBOARD
|
||||
cvCopy(dbg_img, dbg1_img);
|
||||
cvNamedWindow("all_quads", 1);
|
||||
// copy corners to temp array
|
||||
for(int i = 0; i < quad_count; i++ )
|
||||
{
|
||||
for (int k=0; k<4; k++)
|
||||
{
|
||||
CvPoint2D32f pt1, pt2;
|
||||
CvScalar color = CV_RGB(30,255,30);
|
||||
pt1 = quads[i].corners[k]->pt;
|
||||
pt2 = quads[i].corners[(k+1)%4]->pt;
|
||||
pt2.x = (pt1.x + pt2.x)/2;
|
||||
pt2.y = (pt1.y + pt2.y)/2;
|
||||
if (k>0)
|
||||
color = CV_RGB(200,200,0);
|
||||
cvLine( dbg1_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 3, 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cvShowImage("all_quads", (IplImage*)dbg1_img);
|
||||
cvWaitKey();
|
||||
#endif
|
||||
|
||||
if( quad_count <= 0 )
|
||||
continue;
|
||||
|
||||
// Find quad's neighbors
|
||||
icvFindQuadNeighbors( quads, quad_count );
|
||||
|
||||
// allocate extra for adding in icvOrderFoundQuads
|
||||
cvFree(&quad_group);
|
||||
cvFree(&corner_group);
|
||||
quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size);
|
||||
corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 );
|
||||
|
||||
for( group_idx = 0; ; group_idx++ )
|
||||
{
|
||||
int count = 0;
|
||||
count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage );
|
||||
|
||||
int icount = count;
|
||||
if( count == 0 )
|
||||
break;
|
||||
|
||||
// order the quad corners globally
|
||||
// maybe delete or add some
|
||||
PRINTF("Starting ordering of inner quads\n");
|
||||
count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners,
|
||||
pattern_size, max_quad_buf_size, storage );
|
||||
PRINTF("Orig count: %d After ordering: %d\n", icount, count);
|
||||
|
||||
|
||||
#ifdef DEBUG_CHESSBOARD
|
||||
cvCopy(dbg_img,dbg2_img);
|
||||
cvNamedWindow("connected_group", 1);
|
||||
// copy corners to temp array
|
||||
for(int i = 0; i < quad_count; i++ )
|
||||
{
|
||||
if (quads[i].group_idx == group_idx)
|
||||
for (int k=0; k<4; k++)
|
||||
{
|
||||
CvPoint2D32f pt1, pt2;
|
||||
CvScalar color = CV_RGB(30,255,30);
|
||||
if (quads[i].ordered)
|
||||
color = CV_RGB(255,30,30);
|
||||
pt1 = quads[i].corners[k]->pt;
|
||||
pt2 = quads[i].corners[(k+1)%4]->pt;
|
||||
pt2.x = (pt1.x + pt2.x)/2;
|
||||
pt2.y = (pt1.y + pt2.y)/2;
|
||||
if (k>0)
|
||||
color = CV_RGB(200,200,0);
|
||||
cvLine( dbg2_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 3, 8);
|
||||
}
|
||||
}
|
||||
cvShowImage("connected_group", (IplImage*)dbg2_img);
|
||||
cvWaitKey();
|
||||
#endif
|
||||
|
||||
if (count == 0)
|
||||
continue; // haven't found inner quads
|
||||
|
||||
|
||||
// If count is more than it should be, this will remove those quads
|
||||
// which cause maximum deviation from a nice square pattern.
|
||||
count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size );
|
||||
PRINTF("Connected group: %d orig count: %d cleaned: %d\n", group_idx, icount, count);
|
||||
|
||||
count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size );
|
||||
PRINTF("Connected group: %d count: %d cleaned: %d\n", group_idx, icount, count);
|
||||
|
||||
{
|
||||
int n = count > 0 ? pattern_size.width * pattern_size.height : -count;
|
||||
n = MIN( n, pattern_size.width * pattern_size.height );
|
||||
float sum_dist = 0;
|
||||
int total = 0;
|
||||
|
||||
for(int i = 0; i < n; i++ )
|
||||
{
|
||||
int ni = 0;
|
||||
float avgi = corner_group[i]->meanDist(&ni);
|
||||
sum_dist += avgi*ni;
|
||||
total += ni;
|
||||
}
|
||||
prev_sqr_size = cvRound(sum_dist/MAX(total, 1));
|
||||
|
||||
if( count > 0 || (out_corner_count && -count > *out_corner_count) )
|
||||
{
|
||||
// copy corners to output array
|
||||
for(int i = 0; i < n; i++ )
|
||||
out_corners[i] = corner_group[i]->pt;
|
||||
|
||||
if( out_corner_count )
|
||||
*out_corner_count = n;
|
||||
|
||||
if( count == pattern_size.width*pattern_size.height &&
|
||||
icvCheckBoardMonotony( out_corners, pattern_size ))
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( count == pattern_size.width*pattern_size.height && icvCheckBoardMonotony( out_corners, pattern_size ))
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}//dilations
|
||||
}//
|
||||
}// for k = 0 -> 6
|
||||
}
|
||||
|
||||
PRINTF("Chessboard detection result 1: %d\n", found);
|
||||
|
||||
if( found )
|
||||
found = icvCheckBoardMonotony( out_corners, pattern_size );
|
||||
|
||||
PRINTF("Chessboard detection result 2: %d\n", found);
|
||||
|
||||
// check that none of the found corners is too close to the image boundary
|
||||
if( found )
|
||||
{
|
||||
@@ -521,36 +730,38 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
|
||||
found = k == pattern_size.width*pattern_size.height;
|
||||
}
|
||||
|
||||
if( found && pattern_size.height % 2 == 0 && pattern_size.width % 2 == 0 )
|
||||
PRINTF("Chessboard detection result 3: %d\n", found);
|
||||
|
||||
if( found )
|
||||
{
|
||||
if ( pattern_size.height % 2 == 0 && pattern_size.width % 2 == 0 )
|
||||
{
|
||||
int last_row = (pattern_size.height-1)*pattern_size.width;
|
||||
double dy0 = out_corners[last_row].y - out_corners[0].y;
|
||||
if( dy0 < 0 )
|
||||
{
|
||||
int n = pattern_size.width*pattern_size.height;
|
||||
for(int i = 0; i < n/2; i++ )
|
||||
{
|
||||
CvPoint2D32f temp;
|
||||
CV_SWAP(out_corners[i], out_corners[n-i-1], temp);
|
||||
}
|
||||
int n = pattern_size.width*pattern_size.height;
|
||||
for(int i = 0; i < n/2; i++ )
|
||||
{
|
||||
CvPoint2D32f temp;
|
||||
CV_SWAP(out_corners[i], out_corners[n-i-1], temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( found )
|
||||
{
|
||||
cv::Ptr<CvMat> gray;
|
||||
if( CV_MAT_CN(img->type) != 1 )
|
||||
{
|
||||
gray.reset(cvCreateMat(img->rows, img->cols, CV_8UC1));
|
||||
cvCvtColor(img, gray, CV_BGR2GRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
gray.reset(cvCloneMat(img));
|
||||
}
|
||||
int wsize = 2;
|
||||
cvFindCornerSubPix( gray, out_corners, pattern_size.width*pattern_size.height,
|
||||
cvSize(wsize, wsize), cvSize(-1,-1), cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 15, 0.1));
|
||||
}
|
||||
cv::Ptr<CvMat> gray;
|
||||
if( CV_MAT_CN(img->type) != 1 )
|
||||
{
|
||||
gray.reset(cvCreateMat(img->rows, img->cols, CV_8UC1));
|
||||
cvCvtColor(img, gray, CV_BGR2GRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
gray.reset(cvCloneMat(img));
|
||||
}
|
||||
int wsize = 2;
|
||||
cvFindCornerSubPix( gray, out_corners, pattern_size.width*pattern_size.height,
|
||||
cvSize(wsize, wsize), cvSize(-1,-1),
|
||||
cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 15, 0.1));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
@@ -559,6 +770,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
|
||||
cvFree(&corners);
|
||||
cvFree(&quad_group);
|
||||
cvFree(&corner_group);
|
||||
cvFree(&cImgSeg);
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -566,6 +778,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
|
||||
cvFree(&corners);
|
||||
cvFree(&quad_group);
|
||||
cvFree(&corner_group);
|
||||
cvFree(&cImgSeg);
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
@@ -2345,8 +2345,8 @@ void cvStereoRectify( const CvMat* _cameraMatrix1, const CvMat* _cameraMatrix2,
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
int j = (i<2) ? 0 : 1;
|
||||
_pts[i].x = (float)((i % 2)*(nx-1));
|
||||
_pts[i].y = (float)(j*(ny-1));
|
||||
_pts[i].x = (float)((i % 2)*(nx));
|
||||
_pts[i].y = (float)(j*(ny));
|
||||
}
|
||||
cvUndistortPoints( &pts, &pts, A, Dk, 0, 0 );
|
||||
cvConvertPointsHomogeneous( &pts, &pts_3 );
|
||||
@@ -2360,8 +2360,8 @@ void cvStereoRectify( const CvMat* _cameraMatrix1, const CvMat* _cameraMatrix2,
|
||||
_a_tmp[1][2]=0.0;
|
||||
cvProjectPoints2( &pts_3, k == 0 ? _R1 : _R2, &Z, &A_tmp, 0, &pts );
|
||||
CvScalar avg = cvAvg(&pts);
|
||||
cc_new[k].x = (nx-1)/2 - avg.val[0];
|
||||
cc_new[k].y = (ny-1)/2 - avg.val[1];
|
||||
cc_new[k].x = (nx)/2 - avg.val[0];
|
||||
cc_new[k].y = (ny)/2 - avg.val[1];
|
||||
}
|
||||
|
||||
// vertical focal length must be the same for both images to keep the epipolar constraint
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
int cvCheckChessboardBinary(IplImage* src, CvSize size);
|
||||
|
||||
static void icvGetQuadrangleHypotheses(CvSeq* contours, std::vector<std::pair<float, int> >& quads, int class_id)
|
||||
{
|
||||
const float min_aspect_ratio = 0.3f;
|
||||
@@ -205,3 +207,97 @@ int cvCheckChessboard(IplImage* src, CvSize size)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// does a fast check if a chessboard is in the input image. This is a workaround to
|
||||
// a problem of cvFindChessboardCorners being slow on images with no chessboard
|
||||
// - src: input binary image
|
||||
// - size: chessboard size
|
||||
// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called,
|
||||
// 0 if there is no chessboard, -1 in case of error
|
||||
int cvCheckChessboardBinary(IplImage* src, CvSize size)
|
||||
{
|
||||
if(src->nChannels > 1)
|
||||
{
|
||||
cvError(CV_BadNumChannels, "cvCheckChessboard", "supports single-channel images only",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
if(src->depth != 8)
|
||||
{
|
||||
cvError(CV_BadDepth, "cvCheckChessboard", "supports depth=8 images only",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
CvMemStorage* storage = cvCreateMemStorage();
|
||||
|
||||
IplImage* white = cvCloneImage(src);
|
||||
IplImage* black = cvCloneImage(src);
|
||||
IplImage* thresh = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
|
||||
|
||||
int result = 0;
|
||||
|
||||
for ( int erosion_count = 0; erosion_count <= 3; erosion_count++ )
|
||||
{
|
||||
if ( 1 == result )
|
||||
break;
|
||||
|
||||
if ( 0 != erosion_count ) // first iteration keeps original images
|
||||
{
|
||||
cvErode(white, white, NULL, 1);
|
||||
cvDilate(black, black, NULL, 1);
|
||||
}
|
||||
|
||||
cvThreshold(white, thresh, 128, 255, CV_THRESH_BINARY);
|
||||
|
||||
CvSeq* first = 0;
|
||||
std::vector<std::pair<float, int> > quads;
|
||||
cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
|
||||
icvGetQuadrangleHypotheses(first, quads, 1);
|
||||
|
||||
cvThreshold(black, thresh, 128, 255, CV_THRESH_BINARY_INV);
|
||||
cvFindContours(thresh, storage, &first, sizeof(CvContour), CV_RETR_CCOMP);
|
||||
icvGetQuadrangleHypotheses(first, quads, 0);
|
||||
|
||||
const size_t min_quads_count = size.width*size.height/2;
|
||||
std::sort(quads.begin(), quads.end(), less_pred);
|
||||
|
||||
// now check if there are many hypotheses with similar sizes
|
||||
// do this by floodfill-style algorithm
|
||||
const float size_rel_dev = 0.4f;
|
||||
|
||||
for(size_t i = 0; i < quads.size(); i++)
|
||||
{
|
||||
size_t j = i + 1;
|
||||
for(; j < quads.size(); j++)
|
||||
{
|
||||
if(quads[j].first/quads[i].first > 1.0f + size_rel_dev)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(j + 1 > min_quads_count + i)
|
||||
{
|
||||
// check the number of black and white squares
|
||||
std::vector<int> counts;
|
||||
countClasses(quads, i, j, counts);
|
||||
const int black_count = cvRound(ceil(size.width/2.0)*ceil(size.height/2.0));
|
||||
const int white_count = cvRound(floor(size.width/2.0)*floor(size.height/2.0));
|
||||
if(counts[0] < black_count*0.75 ||
|
||||
counts[1] < white_count*0.75)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cvReleaseImage(&thresh);
|
||||
cvReleaseImage(&white);
|
||||
cvReleaseImage(&black);
|
||||
cvReleaseMemStorage(&storage);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
rvec(_rvec), tvec(_tvec) {}
|
||||
|
||||
/* Pre: True */
|
||||
/* Post: compute _model with given points an return number of found models */
|
||||
/* Post: compute _model with given points and return number of found models */
|
||||
int runKernel( InputArray _m1, InputArray _m2, OutputArray _model ) const
|
||||
{
|
||||
Mat opoints = _m1.getMat(), ipoints = _m2.getMat();
|
||||
|
||||
@@ -113,11 +113,7 @@ void CV_ChessboardDetectorTimingTest::run( int start_from )
|
||||
if( img2.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "one of chessboard images can't be read: %s\n", filename.c_str() );
|
||||
if( max_idx == 1 )
|
||||
{
|
||||
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
|
||||
goto _exit_;
|
||||
}
|
||||
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,4 +82,4 @@ Block Matching algorithm has been successfully parallelized using the following
|
||||
3. Merge the results into a single disparity map.
|
||||
|
||||
With this algorithm, a dual GPU gave a 180% performance increase comparing to the single Fermi GPU.
|
||||
For a source code example, see <https://github.com/Itseez/opencv/tree/master/samples/gpu/>.
|
||||
For a source code example, see <https://github.com/opencv/opencv/tree/master/samples/gpu/>.
|
||||
|
||||
@@ -524,6 +524,16 @@ For example:
|
||||
CV_EXPORTS_W void convertScaleAbs(InputArray src, OutputArray dst,
|
||||
double alpha = 1, double beta = 0);
|
||||
|
||||
/** @brief Converts an array to half precision floating number.
|
||||
|
||||
convertFp16 converts FP32 to FP16 or FP16 to FP32. The input array has to have type of CV_32F or
|
||||
CV_16S to represent the bit depth. If the input array is neither of them, it'll do nothing.
|
||||
|
||||
@param src input array.
|
||||
@param dst output array.
|
||||
*/
|
||||
CV_EXPORTS_W void convertFp16(InputArray src, OutputArray dst);
|
||||
|
||||
/** @brief Performs a look-up table transform of an array.
|
||||
|
||||
The function LUT fills the output array with values from the look-up table. Indices of the entries
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
#define CV_CPU_SSE4_1 6
|
||||
#define CV_CPU_SSE4_2 7
|
||||
#define CV_CPU_POPCNT 8
|
||||
|
||||
#define CV_CPU_FP16 9
|
||||
#define CV_CPU_AVX 10
|
||||
#define CV_CPU_AVX2 11
|
||||
#define CV_CPU_FMA3 12
|
||||
@@ -143,7 +143,7 @@ enum CpuFeatures {
|
||||
CPU_SSE4_1 = 6,
|
||||
CPU_SSE4_2 = 7,
|
||||
CPU_POPCNT = 8,
|
||||
|
||||
CPU_FP16 = 9,
|
||||
CPU_AVX = 10,
|
||||
CPU_AVX2 = 11,
|
||||
CPU_FMA3 = 12,
|
||||
@@ -215,7 +215,7 @@ enum CpuFeatures {
|
||||
|
||||
#if (defined WIN32 || defined _WIN32) && defined(_M_ARM)
|
||||
# include <Intrin.h>
|
||||
# include "arm_neon.h"
|
||||
# include <arm_neon.h>
|
||||
# define CV_NEON 1
|
||||
# define CPU_HAS_NEON_FEATURE (true)
|
||||
#elif defined(__ARM_NEON__) || (defined (__ARM_NEON) && defined(__aarch64__))
|
||||
@@ -223,6 +223,10 @@ enum CpuFeatures {
|
||||
# define CV_NEON 1
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_NEON__) || defined(__aarch64__)
|
||||
# include <arm_neon.h>
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__ && defined __arm__ && (defined __ARM_PCS_VFP || defined __ARM_VFPV3__ || defined __ARM_NEON__) && !defined __SOFTFP__
|
||||
# define CV_VFP 1
|
||||
#endif
|
||||
|
||||
@@ -3146,21 +3146,29 @@ The example below illustrates how you can compute a normalized and threshold 3D
|
||||
}
|
||||
|
||||
minProb *= image.rows*image.cols;
|
||||
Mat plane;
|
||||
NAryMatIterator it(&hist, &plane, 1);
|
||||
|
||||
// initialize iterator (the style is different from STL).
|
||||
// after initialization the iterator will contain
|
||||
// the number of slices or planes the iterator will go through.
|
||||
// it simultaneously increments iterators for several matrices
|
||||
// supplied as a null terminated list of pointers
|
||||
const Mat* arrays[] = {&hist, 0};
|
||||
Mat planes[1];
|
||||
NAryMatIterator itNAry(arrays, planes, 1);
|
||||
double s = 0;
|
||||
// iterate through the matrix. on each iteration
|
||||
// it.planes[*] (of type Mat) will be set to the current plane.
|
||||
for(int p = 0; p < it.nplanes; p++, ++it)
|
||||
// itNAry.planes[i] (of type Mat) will be set to the current plane
|
||||
// of the i-th n-dim matrix passed to the iterator constructor.
|
||||
for(int p = 0; p < itNAry.nplanes; p++, ++itNAry)
|
||||
{
|
||||
threshold(it.planes[0], it.planes[0], minProb, 0, THRESH_TOZERO);
|
||||
s += sum(it.planes[0])[0];
|
||||
threshold(itNAry.planes[0], itNAry.planes[0], minProb, 0, THRESH_TOZERO);
|
||||
s += sum(itNAry.planes[0])[0];
|
||||
}
|
||||
|
||||
s = 1./s;
|
||||
it = NAryMatIterator(&hist, &plane, 1);
|
||||
for(int p = 0; p < it.nplanes; p++, ++it)
|
||||
it.planes[0] *= s;
|
||||
itNAry = NAryMatIterator(arrays, planes, 1);
|
||||
for(int p = 0; p < itNAry.nplanes; p++, ++itNAry)
|
||||
itNAry.planes[0] *= s;
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
|
||||
@@ -71,6 +71,17 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined HAVE_FP16 && (defined __F16C__ || (defined _MSC_VER && _MSC_VER >= 1700))
|
||||
# include <immintrin.h>
|
||||
# define CV_FP16 1
|
||||
#elif defined HAVE_FP16 && defined __GNUC__
|
||||
# define CV_FP16 1
|
||||
#endif
|
||||
|
||||
#ifndef CV_FP16
|
||||
# define CV_FP16 0
|
||||
#endif
|
||||
|
||||
//! @cond IGNORED
|
||||
|
||||
namespace cv
|
||||
|
||||
@@ -361,6 +361,17 @@ Ptr<T> makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5&
|
||||
return Ptr<T>(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10));
|
||||
}
|
||||
|
||||
template<typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11>
|
||||
Ptr<T> makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10, const A11& a11)
|
||||
{
|
||||
return Ptr<T>(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11));
|
||||
}
|
||||
|
||||
template<typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12>
|
||||
Ptr<T> makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10, const A11& a11, const A12& a12)
|
||||
{
|
||||
return Ptr<T>(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12));
|
||||
}
|
||||
} // namespace cv
|
||||
|
||||
//! @endcond
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
#define CVAUX_STR_EXP(__A) #__A
|
||||
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
|
||||
|
||||
#define CVAUX_STRW_EXP(__A) L#__A
|
||||
#define CVAUX_STRW_EXP(__A) L ## #__A
|
||||
#define CVAUX_STRW(__A) CVAUX_STRW_EXP(__A)
|
||||
|
||||
#define CV_VERSION CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) "." CVAUX_STR(CV_VERSION_REVISION) CV_VERSION_STATUS
|
||||
|
||||
@@ -643,7 +643,7 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst,
|
||||
if (!muldiv)
|
||||
{
|
||||
Mat sc = psrc2->getMat();
|
||||
depth2 = actualScalarDepth(sc.ptr<double>(), cn);
|
||||
depth2 = actualScalarDepth(sc.ptr<double>(), sz2 == Size(1, 1) ? cn2 : cn);
|
||||
if( depth2 == CV_64F && (depth1 < CV_32S || depth1 == CV_32F) )
|
||||
depth2 = CV_32F;
|
||||
}
|
||||
|
||||
@@ -115,12 +115,13 @@ cvCreateMatHeader( int rows, int cols, int type )
|
||||
{
|
||||
type = CV_MAT_TYPE(type);
|
||||
|
||||
if( rows < 0 || cols <= 0 )
|
||||
if( rows < 0 || cols < 0 )
|
||||
CV_Error( CV_StsBadSize, "Non-positive width or height" );
|
||||
|
||||
int min_step = CV_ELEM_SIZE(type)*cols;
|
||||
int min_step = CV_ELEM_SIZE(type);
|
||||
if( min_step <= 0 )
|
||||
CV_Error( CV_StsUnsupportedFormat, "Invalid matrix type" );
|
||||
min_step *= cols;
|
||||
|
||||
CvMat* arr = (CvMat*)cvAlloc( sizeof(*arr));
|
||||
|
||||
@@ -148,7 +149,7 @@ cvInitMatHeader( CvMat* arr, int rows, int cols,
|
||||
if( (unsigned)CV_MAT_DEPTH(type) > CV_DEPTH_MAX )
|
||||
CV_Error( CV_BadNumChannels, "" );
|
||||
|
||||
if( rows < 0 || cols <= 0 )
|
||||
if( rows < 0 || cols < 0 )
|
||||
CV_Error( CV_StsBadSize, "Non-positive cols or rows" );
|
||||
|
||||
type = CV_MAT_TYPE( type );
|
||||
|
||||
@@ -4361,6 +4361,315 @@ struct Cvt_SIMD<float, int>
|
||||
|
||||
#endif
|
||||
|
||||
#if !( ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) ) )
|
||||
// const numbers for floating points format
|
||||
const unsigned int kShiftSignificand = 13;
|
||||
const unsigned int kMaskFp16Significand = 0x3ff;
|
||||
const unsigned int kBiasFp16Exponent = 15;
|
||||
const unsigned int kBiasFp32Exponent = 127;
|
||||
|
||||
union fp32Int32
|
||||
{
|
||||
int i;
|
||||
float f;
|
||||
struct _fp32Format
|
||||
{
|
||||
unsigned int significand : 23;
|
||||
unsigned int exponent : 8;
|
||||
unsigned int sign : 1;
|
||||
} fmt;
|
||||
};
|
||||
#endif
|
||||
|
||||
union fp16Int16
|
||||
{
|
||||
short i;
|
||||
#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) )
|
||||
__fp16 h;
|
||||
#endif
|
||||
struct _fp16Format
|
||||
{
|
||||
unsigned int significand : 10;
|
||||
unsigned int exponent : 5;
|
||||
unsigned int sign : 1;
|
||||
} fmt;
|
||||
};
|
||||
|
||||
#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) )
|
||||
static float convertFp16SW(short fp16)
|
||||
{
|
||||
// Fp16 -> Fp32
|
||||
fp16Int16 a;
|
||||
a.i = fp16;
|
||||
return (float)a.h;
|
||||
}
|
||||
#else
|
||||
static float convertFp16SW(short fp16)
|
||||
{
|
||||
// Fp16 -> Fp32
|
||||
fp16Int16 b;
|
||||
b.i = fp16;
|
||||
int exponent = b.fmt.exponent - kBiasFp16Exponent;
|
||||
int significand = b.fmt.significand;
|
||||
|
||||
fp32Int32 a;
|
||||
a.i = 0;
|
||||
a.fmt.sign = b.fmt.sign; // sign bit
|
||||
if( exponent == 16 )
|
||||
{
|
||||
// Inf or NaN
|
||||
a.i = a.i | 0x7F800000;
|
||||
if( significand != 0 )
|
||||
{
|
||||
// NaN
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
// 64bit
|
||||
a.i = a.i | 0x7FC00000;
|
||||
#endif
|
||||
a.fmt.significand = a.fmt.significand | (significand << kShiftSignificand);
|
||||
}
|
||||
return a.f;
|
||||
}
|
||||
else if ( exponent == -15 )
|
||||
{
|
||||
// subnormal in Fp16
|
||||
if( significand == 0 )
|
||||
{
|
||||
// zero
|
||||
return a.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
int shift = -1;
|
||||
while( ( significand & 0x400 ) == 0 )
|
||||
{
|
||||
significand = significand << 1;
|
||||
shift++;
|
||||
}
|
||||
significand = significand & kMaskFp16Significand;
|
||||
exponent -= shift;
|
||||
}
|
||||
}
|
||||
|
||||
a.fmt.exponent = (exponent+kBiasFp32Exponent);
|
||||
a.fmt.significand = significand << kShiftSignificand;
|
||||
return a.f;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( defined (__arm__) || defined (__aarch64__) ) && ( defined (__GNUC__) && ( ( ( 4 <= __GNUC__ ) && ( 7 <= __GNUC__ ) ) || ( 5 <= __GNUC__ ) ) )
|
||||
static short convertFp16SW(float fp32)
|
||||
{
|
||||
// Fp32 -> Fp16
|
||||
fp16Int16 a;
|
||||
a.h = (__fp16)fp32;
|
||||
return a.i;
|
||||
}
|
||||
#else
|
||||
static short convertFp16SW(float fp32)
|
||||
{
|
||||
// Fp32 -> Fp16
|
||||
fp32Int32 a;
|
||||
a.f = fp32;
|
||||
int exponent = a.fmt.exponent - kBiasFp32Exponent;
|
||||
int significand = a.fmt.significand;
|
||||
|
||||
fp16Int16 result;
|
||||
result.i = 0;
|
||||
unsigned int absolute = a.i & 0x7fffffff;
|
||||
if( 0x477ff000 <= absolute )
|
||||
{
|
||||
// Inf in Fp16
|
||||
result.i = result.i | 0x7C00;
|
||||
if( exponent == 128 && significand != 0 )
|
||||
{
|
||||
// NaN
|
||||
result.i = (short)( result.i | 0x200 | ( significand >> kShiftSignificand ) );
|
||||
}
|
||||
}
|
||||
else if ( absolute < 0x33000001 )
|
||||
{
|
||||
// too small for fp16
|
||||
result.i = 0;
|
||||
}
|
||||
else if ( absolute < 0x33c00000 )
|
||||
{
|
||||
result.i = 1;
|
||||
}
|
||||
else if ( absolute < 0x34200001 )
|
||||
{
|
||||
result.i = 2;
|
||||
}
|
||||
else if ( absolute < 0x387fe000 )
|
||||
{
|
||||
// subnormal in Fp16
|
||||
int fp16Significand = significand | 0x800000;
|
||||
int bitShift = (-exponent) - 1;
|
||||
fp16Significand = fp16Significand >> bitShift;
|
||||
|
||||
// special cases to round up
|
||||
bitShift = exponent + 24;
|
||||
int threshold = ( ( 0x400000 >> bitShift ) | ( ( ( significand & ( 0x800000 >> bitShift ) ) >> ( 126 - a.fmt.exponent ) ) ^ 1 ) );
|
||||
if( threshold <= ( significand & ( 0xffffff >> ( exponent + 25 ) ) ) )
|
||||
{
|
||||
fp16Significand++;
|
||||
}
|
||||
result.i = (short)fp16Significand;
|
||||
}
|
||||
else
|
||||
{
|
||||
// usual situation
|
||||
// exponent
|
||||
result.fmt.exponent = ( exponent + kBiasFp16Exponent );
|
||||
|
||||
// significand;
|
||||
short fp16Significand = (short)(significand >> kShiftSignificand);
|
||||
result.fmt.significand = fp16Significand;
|
||||
|
||||
// special cases to round up
|
||||
short lsb10bitsFp32 = (significand & 0x1fff);
|
||||
short threshold = 0x1000 + ( ( fp16Significand & 0x1 ) ? 0 : 1 );
|
||||
if( threshold <= lsb10bitsFp32 )
|
||||
{
|
||||
result.i++;
|
||||
}
|
||||
else if ( fp16Significand == 0x3ff && exponent == -15)
|
||||
{
|
||||
result.i++;
|
||||
}
|
||||
}
|
||||
|
||||
// sign bit
|
||||
result.fmt.sign = a.fmt.sign;
|
||||
return result.i;
|
||||
}
|
||||
#endif
|
||||
|
||||
// template for FP16 HW conversion function
|
||||
template<typename T, typename DT> static void
|
||||
cvtScaleHalf_( const T* src, size_t sstep, DT* dst, size_t dstep, Size size)
|
||||
{
|
||||
sstep /= sizeof(src[0]);
|
||||
dstep /= sizeof(dst[0]);
|
||||
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
for ( ; x < size.width; x++ )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<> void
|
||||
cvtScaleHalf_<float, short>( const float* src, size_t sstep, short* dst, size_t dstep, Size size)
|
||||
{
|
||||
sstep /= sizeof(src[0]);
|
||||
dstep /= sizeof(dst[0]);
|
||||
|
||||
if( checkHardwareSupport(CV_CPU_FP16) )
|
||||
{
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
if ( ( (intptr_t)dst & 0xf ) == 0 && ( (intptr_t)src & 0xf ) == 0 )
|
||||
{
|
||||
#if CV_FP16
|
||||
for ( ; x <= size.width - 4; x += 4)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) || defined(i386)
|
||||
__m128 v_src = _mm_load_ps(src + x);
|
||||
|
||||
__m128i v_dst = _mm_cvtps_ph(v_src, 0);
|
||||
|
||||
_mm_storel_epi64((__m128i *)(dst + x), v_dst);
|
||||
#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__)
|
||||
float32x4_t v_src = *(float32x4_t*)(src + x);
|
||||
|
||||
float16x4_t v_dst = vcvt_f16_f32(v_src);
|
||||
|
||||
*(float16x4_t*)(dst + x) = v_dst;
|
||||
#else
|
||||
#error "Configuration error"
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
for ( ; x < size.width; x++ )
|
||||
{
|
||||
dst[x] = convertFp16SW(src[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
int x = 0;
|
||||
for ( ; x < size.width; x++ )
|
||||
{
|
||||
dst[x] = convertFp16SW(src[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<> void
|
||||
cvtScaleHalf_<short, float>( const short* src, size_t sstep, float* dst, size_t dstep, Size size)
|
||||
{
|
||||
sstep /= sizeof(src[0]);
|
||||
dstep /= sizeof(dst[0]);
|
||||
|
||||
if( checkHardwareSupport(CV_CPU_FP16) )
|
||||
{
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
if ( ( (intptr_t)dst & 0xf ) == 0 && ( (intptr_t)src & 0xf ) == 0 && checkHardwareSupport(CV_CPU_FP16) )
|
||||
{
|
||||
#if CV_FP16
|
||||
for ( ; x <= size.width - 4; x += 4)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) || defined(i386)
|
||||
__m128i v_src = _mm_loadl_epi64((__m128i*)(src+x));
|
||||
|
||||
__m128 v_dst = _mm_cvtph_ps(v_src);
|
||||
|
||||
_mm_store_ps((dst + x), v_dst);
|
||||
#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__)
|
||||
float16x4_t v_src = *(float16x4_t*)(src + x);
|
||||
|
||||
float32x4_t v_dst = vcvt_f32_f16(v_src);
|
||||
|
||||
*(float32x4_t*)(dst + x) = v_dst;
|
||||
#else
|
||||
#error "Configuration error"
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
for ( ; x < size.width; x++ )
|
||||
{
|
||||
dst[x] = convertFp16SW(src[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( ; size.height--; src += sstep, dst += dstep )
|
||||
{
|
||||
int x = 0;
|
||||
for ( ; x < size.width; x++ )
|
||||
{
|
||||
dst[x] = convertFp16SW(src[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename DT> static void
|
||||
cvt_( const T* src, size_t sstep,
|
||||
DT* dst, size_t dstep, Size size )
|
||||
@@ -4448,6 +4757,13 @@ static void cvtScaleAbs##suffix( const stype* src, size_t sstep, const uchar*, s
|
||||
tfunc(src, sstep, dst, dstep, size, (wtype)scale[0], (wtype)scale[1]); \
|
||||
}
|
||||
|
||||
#define DEF_CVT_SCALE_FP16_FUNC(suffix, stype, dtype) \
|
||||
static void cvtScaleHalf##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
|
||||
dtype* dst, size_t dstep, Size size, double*) \
|
||||
{ \
|
||||
cvtScaleHalf##_<stype,dtype>(src, sstep, dst, dstep, size); \
|
||||
}
|
||||
|
||||
#define DEF_CVT_SCALE_FUNC(suffix, stype, dtype, wtype) \
|
||||
static void cvtScale##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
|
||||
dtype* dst, size_t dstep, Size size, double* scale) \
|
||||
@@ -4504,6 +4820,9 @@ DEF_CVT_SCALE_ABS_FUNC(32s8u, cvtScaleAbs_, int, uchar, float)
|
||||
DEF_CVT_SCALE_ABS_FUNC(32f8u, cvtScaleAbs_, float, uchar, float)
|
||||
DEF_CVT_SCALE_ABS_FUNC(64f8u, cvtScaleAbs_, double, uchar, float)
|
||||
|
||||
DEF_CVT_SCALE_FP16_FUNC(32f16f, float, short)
|
||||
DEF_CVT_SCALE_FP16_FUNC(16f32f, short, float)
|
||||
|
||||
DEF_CVT_SCALE_FUNC(8u, uchar, uchar, float)
|
||||
DEF_CVT_SCALE_FUNC(8s8u, schar, uchar, float)
|
||||
DEF_CVT_SCALE_FUNC(16u8u, ushort, uchar, float)
|
||||
@@ -4625,6 +4944,17 @@ static BinaryFunc getCvtScaleAbsFunc(int depth)
|
||||
return cvtScaleAbsTab[depth];
|
||||
}
|
||||
|
||||
BinaryFunc getConvertFuncFp16(int ddepth)
|
||||
{
|
||||
static BinaryFunc cvtTab[] =
|
||||
{
|
||||
0, 0, 0,
|
||||
(BinaryFunc)(cvtScaleHalf32f16f), 0, (BinaryFunc)(cvtScaleHalf16f32f),
|
||||
0, 0,
|
||||
};
|
||||
return cvtTab[CV_MAT_DEPTH(ddepth)];
|
||||
}
|
||||
|
||||
BinaryFunc getConvertFunc(int sdepth, int ddepth)
|
||||
{
|
||||
static BinaryFunc cvtTab[][8] =
|
||||
@@ -4809,6 +5139,47 @@ void cv::convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, doubl
|
||||
}
|
||||
}
|
||||
|
||||
void cv::convertFp16( InputArray _src, OutputArray _dst)
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
int ddepth = 0;
|
||||
|
||||
switch( src.depth() )
|
||||
{
|
||||
case CV_32F:
|
||||
ddepth = CV_16S;
|
||||
break;
|
||||
case CV_16S:
|
||||
ddepth = CV_32F;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
int type = CV_MAKETYPE(ddepth, src.channels());
|
||||
_dst.create( src.dims, src.size, type );
|
||||
Mat dst = _dst.getMat();
|
||||
BinaryFunc func = getConvertFuncFp16(ddepth);
|
||||
int cn = src.channels();
|
||||
CV_Assert( func != 0 );
|
||||
|
||||
if( src.dims <= 2 )
|
||||
{
|
||||
Size sz = getContinuousSize(src, dst, cn);
|
||||
func( src.data, src.step, 0, 0, dst.data, dst.step, sz, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const Mat* arrays[] = {&src, &dst, 0};
|
||||
uchar* ptrs[2];
|
||||
NAryMatIterator it(arrays, ptrs);
|
||||
Size sz((int)(it.size*cn), 1);
|
||||
|
||||
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
||||
func(ptrs[0], 1, 0, 0, ptrs[1], 1, sz, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void cv::Mat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const
|
||||
{
|
||||
bool noScale = fabs(alpha-1) < DBL_EPSILON && fabs(beta) < DBL_EPSILON;
|
||||
|
||||
@@ -259,12 +259,6 @@ void Mat::copyTo( OutputArray _dst ) const
|
||||
return;
|
||||
}
|
||||
|
||||
if( empty() )
|
||||
{
|
||||
_dst.release();
|
||||
return;
|
||||
}
|
||||
|
||||
if( _dst.isUMat() )
|
||||
{
|
||||
_dst.create( dims, size.p, type() );
|
||||
|
||||
@@ -839,9 +839,9 @@ void Mat::push_back(const Mat& elems)
|
||||
bool eq = size == elems.size;
|
||||
size.p[0] = r;
|
||||
if( !eq )
|
||||
CV_Error(CV_StsUnmatchedSizes, "");
|
||||
CV_Error(CV_StsUnmatchedSizes, "Pushed vector length is not equal to matrix row length");
|
||||
if( type() != elems.type() )
|
||||
CV_Error(CV_StsUnmatchedFormats, "");
|
||||
CV_Error(CV_StsUnmatchedFormats, "Pushed vector type is not the same as matrix type");
|
||||
|
||||
if( isSubmatrix() || dataend + step.p[0]*delta > datalimit )
|
||||
reserve( std::max(r + delta, (r*3+1)/2) );
|
||||
|
||||
@@ -4234,8 +4234,6 @@ icvReadMat( CvFileStorage* fs, CvFileNode* node )
|
||||
mat = cvCreateMat( rows, cols, elem_type );
|
||||
cvReadRawData( fs, data, mat->data.ptr, dt );
|
||||
}
|
||||
else if( rows == 0 && cols == 0 )
|
||||
mat = cvCreateMatHeader( 0, 1, elem_type );
|
||||
else
|
||||
mat = cvCreateMatHeader( rows, cols, elem_type );
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ typedef void (*BinaryFuncC)(const uchar* src1, size_t step1,
|
||||
uchar* dst, size_t step, int width, int height,
|
||||
void*);
|
||||
|
||||
BinaryFunc getConvertFuncFp16(int ddepth);
|
||||
BinaryFunc getConvertFunc(int sdepth, int ddepth);
|
||||
BinaryFunc getCopyMaskFunc(size_t esz);
|
||||
|
||||
|
||||
@@ -624,7 +624,7 @@ void RNG::fill( InputOutputArray _mat, int disttype,
|
||||
int ptype = depth == CV_64F ? CV_64F : CV_32F;
|
||||
int esz = (int)CV_ELEM_SIZE(ptype);
|
||||
|
||||
if( _param1.isContinuous() && _param1.type() == ptype )
|
||||
if( _param1.isContinuous() && _param1.type() == ptype && n1 >= cn)
|
||||
mean = _param1.ptr();
|
||||
else
|
||||
{
|
||||
@@ -637,18 +637,18 @@ void RNG::fill( InputOutputArray _mat, int disttype,
|
||||
for( j = n1*esz; j < cn*esz; j++ )
|
||||
mean[j] = mean[j - n1*esz];
|
||||
|
||||
if( _param2.isContinuous() && _param2.type() == ptype )
|
||||
if( _param2.isContinuous() && _param2.type() == ptype && n2 >= cn)
|
||||
stddev = _param2.ptr();
|
||||
else
|
||||
{
|
||||
Mat tmp(_param2.size(), ptype, parambuf + cn);
|
||||
Mat tmp(_param2.size(), ptype, parambuf + MAX(n1, cn));
|
||||
_param2.convertTo(tmp, ptype);
|
||||
stddev = (uchar*)(parambuf + cn);
|
||||
stddev = (uchar*)(parambuf + MAX(n1, cn));
|
||||
}
|
||||
|
||||
if( n1 < cn )
|
||||
for( j = n1*esz; j < cn*esz; j++ )
|
||||
stddev[j] = stddev[j - n1*esz];
|
||||
if( n2 < cn )
|
||||
for( j = n2*esz; j < cn*esz; j++ )
|
||||
stddev[j] = stddev[j - n2*esz];
|
||||
|
||||
stdmtx = _param2.rows == cn && _param2.cols == cn;
|
||||
scaleFunc = randnScaleTab[depth];
|
||||
|
||||
@@ -291,6 +291,7 @@ struct HWFeatures
|
||||
f.have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0;
|
||||
f.have[CV_CPU_POPCNT] = (cpuid_data[2] & (1<<23)) != 0;
|
||||
f.have[CV_CPU_AVX] = (((cpuid_data[2] & (1<<28)) != 0)&&((cpuid_data[2] & (1<<27)) != 0));//OS uses XSAVE_XRSTORE and CPU support AVX
|
||||
f.have[CV_CPU_FP16] = (cpuid_data[2] & (1<<29)) != 0;
|
||||
|
||||
// make the second call to the cpuid command in order to get
|
||||
// information about extended features like AVX2
|
||||
@@ -338,7 +339,8 @@ struct HWFeatures
|
||||
#if defined ANDROID || defined __linux__
|
||||
#ifdef __aarch64__
|
||||
f.have[CV_CPU_NEON] = true;
|
||||
#else
|
||||
f.have[CV_CPU_FP16] = true;
|
||||
#elif defined __arm__
|
||||
int cpufile = open("/proc/self/auxv", O_RDONLY);
|
||||
|
||||
if (cpufile >= 0)
|
||||
@@ -351,6 +353,7 @@ struct HWFeatures
|
||||
if (auxv.a_type == AT_HWCAP)
|
||||
{
|
||||
f.have[CV_CPU_NEON] = (auxv.a_un.a_val & 4096) != 0;
|
||||
f.have[CV_CPU_FP16] = (auxv.a_un.a_val & 2) != 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -358,8 +361,13 @@ struct HWFeatures
|
||||
close(cpufile);
|
||||
}
|
||||
#endif
|
||||
#elif (defined __clang__ || defined __APPLE__) && (defined __ARM_NEON__ || (defined __ARM_NEON && defined __aarch64__))
|
||||
#elif (defined __clang__ || defined __APPLE__)
|
||||
#if (defined __ARM_NEON__ || (defined __ARM_NEON && defined __aarch64__))
|
||||
f.have[CV_CPU_NEON] = true;
|
||||
#endif
|
||||
#if (defined __ARM_FP && (((__ARM_FP & 0x2) != 0) && defined __ARM_NEON__))
|
||||
f.have[CV_CPU_FP16] = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return f;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
#include "test_precomp.hpp"
|
||||
#include <cmath>
|
||||
#ifndef NAN
|
||||
#include <limits> // numeric_limits<T>::quiet_NaN()
|
||||
#define NAN std::numeric_limits<float>::quiet_NaN()
|
||||
#endif
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
@@ -737,6 +742,62 @@ struct ConvertScaleOp : public BaseElemWiseOp
|
||||
int ddepth;
|
||||
};
|
||||
|
||||
struct ConvertScaleFp16Op : public BaseElemWiseOp
|
||||
{
|
||||
ConvertScaleFp16Op() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)), nextRange(0) { }
|
||||
void op(const vector<Mat>& src, Mat& dst, const Mat&)
|
||||
{
|
||||
Mat m;
|
||||
convertFp16(src[0], m);
|
||||
convertFp16(m, dst);
|
||||
}
|
||||
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
|
||||
{
|
||||
cvtest::copy(src[0], dst);
|
||||
}
|
||||
int getRandomType(RNG&)
|
||||
{
|
||||
// 0: FP32 -> FP16 -> FP32
|
||||
// 1: FP16 -> FP32 -> FP16
|
||||
int srctype = (nextRange & 1) == 0 ? CV_32F : CV_16S;
|
||||
return srctype;
|
||||
}
|
||||
void getValueRange(int, double& minval, double& maxval)
|
||||
{
|
||||
// 0: FP32 -> FP16 -> FP32
|
||||
// 1: FP16 -> FP32 -> FP16
|
||||
if( (nextRange & 1) == 0 )
|
||||
{
|
||||
// largest integer number that fp16 can express exactly
|
||||
maxval = 2048.f;
|
||||
minval = -maxval;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 0: positive number range
|
||||
// 1: negative number range
|
||||
if( (nextRange & 2) == 0 )
|
||||
{
|
||||
minval = 0; // 0x0000 +0
|
||||
maxval = 31744; // 0x7C00 +Inf
|
||||
}
|
||||
else
|
||||
{
|
||||
minval = -32768; // 0x8000 -0
|
||||
maxval = -1024; // 0xFC00 -Inf
|
||||
}
|
||||
}
|
||||
}
|
||||
double getMaxErr(int)
|
||||
{
|
||||
return 0.5f;
|
||||
}
|
||||
void generateScalars(int, RNG& rng)
|
||||
{
|
||||
nextRange = rng.next();
|
||||
}
|
||||
int nextRange;
|
||||
};
|
||||
|
||||
struct ConvertScaleAbsOp : public BaseElemWiseOp
|
||||
{
|
||||
@@ -1371,6 +1432,7 @@ INSTANTIATE_TEST_CASE_P(Core_Copy, ElemWiseTest, ::testing::Values(ElemWiseOpPtr
|
||||
INSTANTIATE_TEST_CASE_P(Core_Set, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SetOp)));
|
||||
INSTANTIATE_TEST_CASE_P(Core_SetZero, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SetZeroOp)));
|
||||
INSTANTIATE_TEST_CASE_P(Core_ConvertScale, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ConvertScaleOp)));
|
||||
INSTANTIATE_TEST_CASE_P(Core_ConvertScaleFp16, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ConvertScaleFp16Op)));
|
||||
INSTANTIATE_TEST_CASE_P(Core_ConvertScaleAbs, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ConvertScaleAbsOp)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Core_Add, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AddOp)));
|
||||
@@ -1853,3 +1915,21 @@ TEST(MinMaxLoc, regression_4955_nans)
|
||||
cv::Mat nan_mat(2, 2, CV_32F, cv::Scalar(NAN));
|
||||
cv::minMaxLoc(nan_mat, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
TEST(Subtract, scalarc1_matc3)
|
||||
{
|
||||
int scalar = 255;
|
||||
cv::Mat srcImage(5, 5, CV_8UC3, cv::Scalar::all(5)), destImage;
|
||||
cv::subtract(scalar, srcImage, destImage);
|
||||
|
||||
ASSERT_EQ(0, cv::norm(cv::Mat(5, 5, CV_8UC3, cv::Scalar::all(250)), destImage, cv::NORM_INF));
|
||||
}
|
||||
|
||||
TEST(Subtract, scalarc4_matc4)
|
||||
{
|
||||
cv::Scalar sc(255, 255, 255, 255);
|
||||
cv::Mat srcImage(5, 5, CV_8UC4, cv::Scalar::all(5)), destImage;
|
||||
cv::subtract(sc, srcImage, destImage);
|
||||
|
||||
ASSERT_EQ(0, cv::norm(cv::Mat(5, 5, CV_8UC4, cv::Scalar::all(250)), destImage, cv::NORM_INF));
|
||||
}
|
||||
|
||||
@@ -593,3 +593,287 @@ TEST(Core_InputOutput, FileStorageSpaces)
|
||||
ASSERT_STREQ(values[i].c_str(), valuesRead[i].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
struct data_t
|
||||
{
|
||||
typedef uchar u;
|
||||
typedef char b;
|
||||
typedef ushort w;
|
||||
typedef short s;
|
||||
typedef int i;
|
||||
typedef float f;
|
||||
typedef double d;
|
||||
|
||||
u u1 ;u u2 ; i i1 ;
|
||||
i i2 ;i i3 ;
|
||||
d d1 ;
|
||||
d d2 ;
|
||||
i i4 ;
|
||||
|
||||
static inline const char * signature() { return "2u3i2di"; }
|
||||
};
|
||||
|
||||
TEST(Core_InputOutput, filestorage_base64_basic)
|
||||
{
|
||||
char const * filenames[] = {
|
||||
"core_io_base64_basic_test.yml",
|
||||
"core_io_base64_basic_test.xml",
|
||||
0
|
||||
};
|
||||
|
||||
for (char const ** ptr = filenames; *ptr; ptr++)
|
||||
{
|
||||
char const * name = *ptr;
|
||||
|
||||
std::vector<data_t> rawdata;
|
||||
|
||||
cv::Mat _em_out, _em_in;
|
||||
cv::Mat _2d_out, _2d_in;
|
||||
cv::Mat _nd_out, _nd_in;
|
||||
cv::Mat _rd_out(64, 64, CV_64FC1), _rd_in;
|
||||
|
||||
{ /* init */
|
||||
|
||||
/* a normal mat */
|
||||
_2d_out = cv::Mat(100, 100, CV_8UC3, cvScalar(1U, 2U, 127U));
|
||||
for (int i = 0; i < _2d_out.rows; ++i)
|
||||
for (int j = 0; j < _2d_out.cols; ++j)
|
||||
_2d_out.at<cv::Vec3b>(i, j)[1] = (i + j) % 256;
|
||||
|
||||
/* a 4d mat */
|
||||
const int Size[] = {4, 4, 4, 4};
|
||||
cv::Mat _4d(4, Size, CV_64FC4, cvScalar(0.888, 0.111, 0.666, 0.444));
|
||||
const cv::Range ranges[] = {
|
||||
cv::Range(0, 2),
|
||||
cv::Range(0, 2),
|
||||
cv::Range(1, 2),
|
||||
cv::Range(0, 2) };
|
||||
_nd_out = _4d(ranges);
|
||||
|
||||
/* a random mat */
|
||||
cv::randu(_rd_out, cv::Scalar(0.0), cv::Scalar(1.0));
|
||||
|
||||
/* raw data */
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
data_t tmp;
|
||||
tmp.u1 = 1;
|
||||
tmp.u2 = 2;
|
||||
tmp.i1 = 1;
|
||||
tmp.i2 = 2;
|
||||
tmp.i3 = 3;
|
||||
tmp.d1 = 0.1;
|
||||
tmp.d2 = 0.2;
|
||||
tmp.i4 = i;
|
||||
rawdata.push_back(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
{ /* write */
|
||||
cv::FileStorage fs(name, cv::FileStorage::WRITE_BASE64);
|
||||
fs << "normal_2d_mat" << _2d_out;
|
||||
fs << "normal_nd_mat" << _nd_out;
|
||||
fs << "empty_2d_mat" << _em_out;
|
||||
fs << "random_mat" << _rd_out;
|
||||
|
||||
cvStartWriteStruct( *fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW, "binary" );
|
||||
for (int i = 0; i < 10; i++)
|
||||
cvWriteRawDataBase64(*fs, rawdata.data() + i * 100, 100, data_t::signature());
|
||||
cvEndWriteStruct( *fs );
|
||||
|
||||
fs.release();
|
||||
}
|
||||
|
||||
{ /* read */
|
||||
cv::FileStorage fs(name, cv::FileStorage::READ);
|
||||
|
||||
/* mat */
|
||||
fs["empty_2d_mat"] >> _em_in;
|
||||
fs["normal_2d_mat"] >> _2d_in;
|
||||
fs["normal_nd_mat"] >> _nd_in;
|
||||
fs["random_mat"] >> _rd_in;
|
||||
|
||||
/* raw data */
|
||||
std::vector<data_t>(1000).swap(rawdata);
|
||||
cvReadRawData(*fs, fs["rawdata"].node, rawdata.data(), data_t::signature());
|
||||
|
||||
fs.release();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
// TODO: Solve this bug in `cvReadRawData`
|
||||
//EXPECT_EQ(rawdata[i].u1, 1);
|
||||
//EXPECT_EQ(rawdata[i].u2, 2);
|
||||
//EXPECT_EQ(rawdata[i].i1, 1);
|
||||
//EXPECT_EQ(rawdata[i].i2, 2);
|
||||
//EXPECT_EQ(rawdata[i].i3, 3);
|
||||
//EXPECT_EQ(rawdata[i].d1, 0.1);
|
||||
//EXPECT_EQ(rawdata[i].d2, 0.2);
|
||||
//EXPECT_EQ(rawdata[i].i4, i);
|
||||
}
|
||||
|
||||
EXPECT_EQ(_em_in.rows , _em_out.rows);
|
||||
EXPECT_EQ(_em_in.cols , _em_out.cols);
|
||||
EXPECT_EQ(_em_in.depth(), _em_out.depth());
|
||||
EXPECT_TRUE(_em_in.empty());
|
||||
|
||||
EXPECT_EQ(_2d_in.rows , _2d_out.rows);
|
||||
EXPECT_EQ(_2d_in.cols , _2d_out.cols);
|
||||
EXPECT_EQ(_2d_in.dims , _2d_out.dims);
|
||||
EXPECT_EQ(_2d_in.depth(), _2d_out.depth());
|
||||
for(int i = 0; i < _2d_out.rows; ++i)
|
||||
for (int j = 0; j < _2d_out.cols; ++j)
|
||||
EXPECT_EQ(_2d_in.at<cv::Vec3b>(i, j), _2d_out.at<cv::Vec3b>(i, j));
|
||||
|
||||
EXPECT_EQ(_nd_in.rows , _nd_out.rows);
|
||||
EXPECT_EQ(_nd_in.cols , _nd_out.cols);
|
||||
EXPECT_EQ(_nd_in.dims , _nd_out.dims);
|
||||
EXPECT_EQ(_nd_in.depth(), _nd_out.depth());
|
||||
EXPECT_EQ(cv::countNonZero(cv::mean(_nd_in != _nd_out)), 0);
|
||||
|
||||
EXPECT_EQ(_rd_in.rows , _rd_out.rows);
|
||||
EXPECT_EQ(_rd_in.cols , _rd_out.cols);
|
||||
EXPECT_EQ(_rd_in.dims , _rd_out.dims);
|
||||
EXPECT_EQ(_rd_in.depth(), _rd_out.depth());
|
||||
EXPECT_EQ(cv::countNonZero(cv::mean(_rd_in != _rd_out)), 0);
|
||||
|
||||
remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_InputOutput, filestorage_base64_valid_call)
|
||||
{
|
||||
char const * filenames[] = {
|
||||
"core_io_base64_other_test.yml",
|
||||
"core_io_base64_other_test.xml",
|
||||
"core_io_base64_other_test.yml?base64",
|
||||
"core_io_base64_other_test.xml?base64",
|
||||
0
|
||||
};
|
||||
char const * real_name[] = {
|
||||
"core_io_base64_other_test.yml",
|
||||
"core_io_base64_other_test.xml",
|
||||
"core_io_base64_other_test.yml",
|
||||
"core_io_base64_other_test.xml",
|
||||
0
|
||||
};
|
||||
|
||||
std::vector<int> rawdata(10, static_cast<int>(0x00010203));
|
||||
cv::String str_out = "test_string";
|
||||
|
||||
for (char const ** ptr = filenames; *ptr; ptr++)
|
||||
{
|
||||
char const * name = *ptr;
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
{
|
||||
cv::FileStorage fs(name, cv::FileStorage::WRITE_BASE64);
|
||||
|
||||
cvStartWriteStruct(*fs, "manydata", CV_NODE_SEQ);
|
||||
cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW);
|
||||
for (int i = 0; i < 10; i++)
|
||||
cvWriteRawData(*fs, rawdata.data(), static_cast<int>(rawdata.size()), "i");
|
||||
cvEndWriteStruct(*fs);
|
||||
cvWriteString(*fs, 0, str_out.c_str(), 1);
|
||||
cvEndWriteStruct(*fs);
|
||||
|
||||
fs.release();
|
||||
});
|
||||
|
||||
{
|
||||
cv::FileStorage fs(name, cv::FileStorage::READ);
|
||||
std::vector<int> data_in(rawdata.size());
|
||||
fs["manydata"][0].readRaw("i", (uchar *)data_in.data(), data_in.size());
|
||||
EXPECT_TRUE(fs["manydata"][0].isSeq());
|
||||
EXPECT_TRUE(std::equal(rawdata.begin(), rawdata.end(), data_in.begin()));
|
||||
cv::String str_in;
|
||||
fs["manydata"][1] >> str_in;
|
||||
EXPECT_TRUE(fs["manydata"][1].isString());
|
||||
EXPECT_EQ(str_in, str_out);
|
||||
fs.release();
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
{
|
||||
cv::FileStorage fs(name, cv::FileStorage::WRITE);
|
||||
|
||||
cvStartWriteStruct(*fs, "manydata", CV_NODE_SEQ);
|
||||
cvWriteString(*fs, 0, str_out.c_str(), 1);
|
||||
cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW, "binary");
|
||||
for (int i = 0; i < 10; i++)
|
||||
cvWriteRawData(*fs, rawdata.data(), static_cast<int>(rawdata.size()), "i");
|
||||
cvEndWriteStruct(*fs);
|
||||
cvEndWriteStruct(*fs);
|
||||
|
||||
fs.release();
|
||||
});
|
||||
|
||||
{
|
||||
cv::FileStorage fs(name, cv::FileStorage::READ);
|
||||
cv::String str_in;
|
||||
fs["manydata"][0] >> str_in;
|
||||
EXPECT_TRUE(fs["manydata"][0].isString());
|
||||
EXPECT_EQ(str_in, str_out);
|
||||
std::vector<int> data_in(rawdata.size());
|
||||
fs["manydata"][1].readRaw("i", (uchar *)data_in.data(), data_in.size());
|
||||
EXPECT_TRUE(fs["manydata"][1].isSeq());
|
||||
EXPECT_TRUE(std::equal(rawdata.begin(), rawdata.end(), data_in.begin()));
|
||||
fs.release();
|
||||
}
|
||||
|
||||
remove(real_name[ptr - filenames]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_InputOutput, filestorage_base64_invalid_call)
|
||||
{
|
||||
char const * filenames[] = {
|
||||
"core_io_base64_other_test.yml",
|
||||
"core_io_base64_other_test.xml",
|
||||
0
|
||||
};
|
||||
|
||||
for (char const ** ptr = filenames; *ptr; ptr++)
|
||||
{
|
||||
char const * name = *ptr;
|
||||
|
||||
EXPECT_ANY_THROW({
|
||||
cv::FileStorage fs(name, cv::FileStorage::WRITE);
|
||||
cvStartWriteStruct(*fs, "rawdata", CV_NODE_SEQ, "binary");
|
||||
cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW);
|
||||
});
|
||||
|
||||
EXPECT_ANY_THROW({
|
||||
cv::FileStorage fs(name, cv::FileStorage::WRITE);
|
||||
cvStartWriteStruct(*fs, "rawdata", CV_NODE_SEQ);
|
||||
cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW);
|
||||
cvWriteRawDataBase64(*fs, name, 1, "u");
|
||||
});
|
||||
|
||||
remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_InputOutput, filestorage_yml_vec2i)
|
||||
{
|
||||
const std::string file_name = "vec2i.yml";
|
||||
cv::Vec2i vec(2, 1), ovec;
|
||||
|
||||
/* write */
|
||||
{
|
||||
cv::FileStorage fs(file_name, cv::FileStorage::WRITE);
|
||||
fs << "prms0" << "{" << "vec0" << vec << "}";
|
||||
fs.release();
|
||||
}
|
||||
|
||||
/* read */
|
||||
{
|
||||
cv::FileStorage fs(file_name, cv::FileStorage::READ);
|
||||
fs["prms0"]["vec0"] >> ovec;
|
||||
fs.release();
|
||||
}
|
||||
|
||||
EXPECT_EQ(vec(0), ovec(0));
|
||||
EXPECT_EQ(vec(1), ovec(1));
|
||||
|
||||
remove(file_name.c_str());
|
||||
}
|
||||
|
||||
@@ -1,270 +0,0 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
struct data_t
|
||||
{
|
||||
typedef uchar u;
|
||||
typedef char b;
|
||||
typedef ushort w;
|
||||
typedef short s;
|
||||
typedef int i;
|
||||
typedef float f;
|
||||
typedef double d;
|
||||
|
||||
u u1 ;u u2 ; i i1 ;
|
||||
i i2 ;i i3 ;
|
||||
d d1 ;
|
||||
d d2 ;
|
||||
i i4 ;
|
||||
|
||||
static inline const char * signature() { return "2u3i2di"; }
|
||||
};
|
||||
|
||||
|
||||
TEST(Core_InputOutput_Base64, basic)
|
||||
{
|
||||
char const * filenames[] = {
|
||||
"core_io_base64_basic_test.yml",
|
||||
"core_io_base64_basic_test.xml",
|
||||
0
|
||||
};
|
||||
|
||||
for (char const ** ptr = filenames; *ptr; ptr++)
|
||||
{
|
||||
char const * name = *ptr;
|
||||
|
||||
std::vector<data_t> rawdata;
|
||||
|
||||
cv::Mat _em_out, _em_in;
|
||||
cv::Mat _2d_out, _2d_in;
|
||||
cv::Mat _nd_out, _nd_in;
|
||||
cv::Mat _rd_out(64, 64, CV_64FC1), _rd_in;
|
||||
|
||||
{ /* init */
|
||||
|
||||
/* a normal mat */
|
||||
_2d_out = cv::Mat(100, 100, CV_8UC3, cvScalar(1U, 2U, 127U));
|
||||
for (int i = 0; i < _2d_out.rows; ++i)
|
||||
for (int j = 0; j < _2d_out.cols; ++j)
|
||||
_2d_out.at<cv::Vec3b>(i, j)[1] = (i + j) % 256;
|
||||
|
||||
/* a 4d mat */
|
||||
const int Size[] = {4, 4, 4, 4};
|
||||
cv::Mat _4d(4, Size, CV_64FC4, cvScalar(0.888, 0.111, 0.666, 0.444));
|
||||
const cv::Range ranges[] = {
|
||||
cv::Range(0, 2),
|
||||
cv::Range(0, 2),
|
||||
cv::Range(1, 2),
|
||||
cv::Range(0, 2) };
|
||||
_nd_out = _4d(ranges);
|
||||
|
||||
/* a random mat */
|
||||
cv::randu(_rd_out, cv::Scalar(0.0), cv::Scalar(1.0));
|
||||
|
||||
/* raw data */
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
data_t tmp;
|
||||
tmp.u1 = 1;
|
||||
tmp.u2 = 2;
|
||||
tmp.i1 = 1;
|
||||
tmp.i2 = 2;
|
||||
tmp.i3 = 3;
|
||||
tmp.d1 = 0.1;
|
||||
tmp.d2 = 0.2;
|
||||
tmp.i4 = i;
|
||||
rawdata.push_back(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
{ /* write */
|
||||
cv::FileStorage fs(name, cv::FileStorage::WRITE_BASE64);
|
||||
fs << "normal_2d_mat" << _2d_out;
|
||||
fs << "normal_nd_mat" << _nd_out;
|
||||
fs << "empty_2d_mat" << _em_out;
|
||||
fs << "random_mat" << _rd_out;
|
||||
|
||||
cvStartWriteStruct( *fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW, "binary" );
|
||||
for (int i = 0; i < 10; i++)
|
||||
cvWriteRawDataBase64(*fs, rawdata.data() + i * 100, 100, data_t::signature());
|
||||
cvEndWriteStruct( *fs );
|
||||
|
||||
fs.release();
|
||||
}
|
||||
|
||||
{ /* read */
|
||||
cv::FileStorage fs(name, cv::FileStorage::READ);
|
||||
|
||||
/* mat */
|
||||
fs["empty_2d_mat"] >> _em_in;
|
||||
fs["normal_2d_mat"] >> _2d_in;
|
||||
fs["normal_nd_mat"] >> _nd_in;
|
||||
fs["random_mat"] >> _rd_in;
|
||||
|
||||
/* raw data */
|
||||
std::vector<data_t>(1000).swap(rawdata);
|
||||
cvReadRawData(*fs, fs["rawdata"].node, rawdata.data(), data_t::signature());
|
||||
|
||||
fs.release();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
// TODO: Solve this bug in `cvReadRawData`
|
||||
//EXPECT_EQ(rawdata[i].u1, 1);
|
||||
//EXPECT_EQ(rawdata[i].u2, 2);
|
||||
//EXPECT_EQ(rawdata[i].i1, 1);
|
||||
//EXPECT_EQ(rawdata[i].i2, 2);
|
||||
//EXPECT_EQ(rawdata[i].i3, 3);
|
||||
//EXPECT_EQ(rawdata[i].d1, 0.1);
|
||||
//EXPECT_EQ(rawdata[i].d2, 0.2);
|
||||
//EXPECT_EQ(rawdata[i].i4, i);
|
||||
}
|
||||
|
||||
EXPECT_EQ(_em_in.rows , _em_out.rows);
|
||||
EXPECT_EQ(_em_in.cols , _em_out.cols);
|
||||
EXPECT_EQ(_em_in.dims , _em_out.dims);
|
||||
EXPECT_EQ(_em_in.depth(), _em_out.depth());
|
||||
EXPECT_TRUE(_em_in.empty());
|
||||
|
||||
EXPECT_EQ(_2d_in.rows , _2d_out.rows);
|
||||
EXPECT_EQ(_2d_in.cols , _2d_out.cols);
|
||||
EXPECT_EQ(_2d_in.dims , _2d_out.dims);
|
||||
EXPECT_EQ(_2d_in.depth(), _2d_out.depth());
|
||||
for(int i = 0; i < _2d_out.rows; ++i)
|
||||
for (int j = 0; j < _2d_out.cols; ++j)
|
||||
EXPECT_EQ(_2d_in.at<cv::Vec3b>(i, j), _2d_out.at<cv::Vec3b>(i, j));
|
||||
|
||||
EXPECT_EQ(_nd_in.rows , _nd_out.rows);
|
||||
EXPECT_EQ(_nd_in.cols , _nd_out.cols);
|
||||
EXPECT_EQ(_nd_in.dims , _nd_out.dims);
|
||||
EXPECT_EQ(_nd_in.depth(), _nd_out.depth());
|
||||
EXPECT_EQ(cv::countNonZero(cv::mean(_nd_in != _nd_out)), 0);
|
||||
|
||||
EXPECT_EQ(_rd_in.rows , _rd_out.rows);
|
||||
EXPECT_EQ(_rd_in.cols , _rd_out.cols);
|
||||
EXPECT_EQ(_rd_in.dims , _rd_out.dims);
|
||||
EXPECT_EQ(_rd_in.depth(), _rd_out.depth());
|
||||
EXPECT_EQ(cv::countNonZero(cv::mean(_rd_in != _rd_out)), 0);
|
||||
|
||||
remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_InputOutput_Base64, valid)
|
||||
{
|
||||
char const * filenames[] = {
|
||||
"core_io_base64_other_test.yml",
|
||||
"core_io_base64_other_test.xml",
|
||||
"core_io_base64_other_test.yml?base64",
|
||||
"core_io_base64_other_test.xml?base64",
|
||||
0
|
||||
};
|
||||
char const * real_name[] = {
|
||||
"core_io_base64_other_test.yml",
|
||||
"core_io_base64_other_test.xml",
|
||||
"core_io_base64_other_test.yml",
|
||||
"core_io_base64_other_test.xml",
|
||||
0
|
||||
};
|
||||
|
||||
std::vector<int> rawdata(10, static_cast<int>(0x00010203));
|
||||
cv::String str_out = "test_string";
|
||||
|
||||
for (char const ** ptr = filenames; *ptr; ptr++)
|
||||
{
|
||||
char const * name = *ptr;
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
{
|
||||
cv::FileStorage fs(name, cv::FileStorage::WRITE_BASE64);
|
||||
|
||||
cvStartWriteStruct(*fs, "manydata", CV_NODE_SEQ);
|
||||
cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW);
|
||||
for (int i = 0; i < 10; i++)
|
||||
cvWriteRawData(*fs, rawdata.data(), static_cast<int>(rawdata.size()), "i");
|
||||
cvEndWriteStruct(*fs);
|
||||
cvWriteString(*fs, 0, str_out.c_str(), 1);
|
||||
cvEndWriteStruct(*fs);
|
||||
|
||||
fs.release();
|
||||
});
|
||||
|
||||
{
|
||||
cv::FileStorage fs(name, cv::FileStorage::READ);
|
||||
std::vector<int> data_in(rawdata.size());
|
||||
fs["manydata"][0].readRaw("i", (uchar *)data_in.data(), data_in.size());
|
||||
EXPECT_TRUE(fs["manydata"][0].isSeq());
|
||||
EXPECT_TRUE(std::equal(rawdata.begin(), rawdata.end(), data_in.begin()));
|
||||
cv::String str_in;
|
||||
fs["manydata"][1] >> str_in;
|
||||
EXPECT_TRUE(fs["manydata"][1].isString());
|
||||
EXPECT_EQ(str_in, str_out);
|
||||
fs.release();
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
{
|
||||
cv::FileStorage fs(name, cv::FileStorage::WRITE);
|
||||
|
||||
cvStartWriteStruct(*fs, "manydata", CV_NODE_SEQ);
|
||||
cvWriteString(*fs, 0, str_out.c_str(), 1);
|
||||
cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW, "binary");
|
||||
for (int i = 0; i < 10; i++)
|
||||
cvWriteRawData(*fs, rawdata.data(), static_cast<int>(rawdata.size()), "i");
|
||||
cvEndWriteStruct(*fs);
|
||||
cvEndWriteStruct(*fs);
|
||||
|
||||
fs.release();
|
||||
});
|
||||
|
||||
{
|
||||
cv::FileStorage fs(name, cv::FileStorage::READ);
|
||||
cv::String str_in;
|
||||
fs["manydata"][0] >> str_in;
|
||||
EXPECT_TRUE(fs["manydata"][0].isString());
|
||||
EXPECT_EQ(str_in, str_out);
|
||||
std::vector<int> data_in(rawdata.size());
|
||||
fs["manydata"][1].readRaw("i", (uchar *)data_in.data(), data_in.size());
|
||||
EXPECT_TRUE(fs["manydata"][1].isSeq());
|
||||
EXPECT_TRUE(std::equal(rawdata.begin(), rawdata.end(), data_in.begin()));
|
||||
fs.release();
|
||||
}
|
||||
|
||||
remove(real_name[ptr - filenames]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_InputOutput_Base64, invalid)
|
||||
{
|
||||
char const * filenames[] = {
|
||||
"core_io_base64_other_test.yml",
|
||||
"core_io_base64_other_test.xml",
|
||||
0
|
||||
};
|
||||
|
||||
for (char const ** ptr = filenames; *ptr; ptr++)
|
||||
{
|
||||
char const * name = *ptr;
|
||||
|
||||
EXPECT_ANY_THROW({
|
||||
cv::FileStorage fs(name, cv::FileStorage::WRITE);
|
||||
cvStartWriteStruct(*fs, "rawdata", CV_NODE_SEQ, "binary");
|
||||
cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW);
|
||||
});
|
||||
|
||||
EXPECT_ANY_THROW({
|
||||
cv::FileStorage fs(name, cv::FileStorage::WRITE);
|
||||
cvStartWriteStruct(*fs, "rawdata", CV_NODE_SEQ);
|
||||
cvStartWriteStruct(*fs, 0, CV_NODE_SEQ | CV_NODE_FLOW);
|
||||
cvWriteRawDataBase64(*fs, name, 1, "u");
|
||||
});
|
||||
|
||||
remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_InputOutput_Base64, TODO_compatibility)
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
@@ -1392,7 +1392,7 @@ TEST(Core_SparseMat, footprint)
|
||||
}
|
||||
|
||||
|
||||
// Can't fix without duty hacks or broken user code (PR #4159)
|
||||
// Can't fix without dirty hacks or broken user code (PR #4159)
|
||||
TEST(Core_Mat_vector, DISABLED_OutputArray_create_getMat)
|
||||
{
|
||||
cv::Mat_<uchar> src_base(5, 1);
|
||||
@@ -1420,7 +1420,7 @@ TEST(Core_Mat_vector, copyTo_roi_column)
|
||||
|
||||
Mat src_full(src_base);
|
||||
Mat src(src_full.col(0));
|
||||
#if 0 // Can't fix without duty hacks or broken user code (PR #4159)
|
||||
#if 0 // Can't fix without dirty hacks or broken user code (PR #4159)
|
||||
OutputArray _dst(dst1);
|
||||
{
|
||||
_dst.create(src.rows, src.cols, src.type());
|
||||
@@ -1520,3 +1520,29 @@ TEST(Reduce, regression_should_fail_bug_4594)
|
||||
EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_SUM, CV_32S));
|
||||
EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_AVG, CV_32S));
|
||||
}
|
||||
|
||||
TEST(Mat, push_back_vector)
|
||||
{
|
||||
cv::Mat result(1, 5, CV_32FC1);
|
||||
|
||||
std::vector<float> vec1(result.cols + 1);
|
||||
std::vector<int> vec2(result.cols);
|
||||
|
||||
EXPECT_THROW(result.push_back(vec1), cv::Exception);
|
||||
EXPECT_THROW(result.push_back(vec2), cv::Exception);
|
||||
|
||||
vec1.resize(result.cols);
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
result.push_back(cv::Mat(vec1).reshape(1, 1));
|
||||
|
||||
ASSERT_EQ(6, result.rows);
|
||||
}
|
||||
|
||||
TEST(Mat, regression_5917_clone_empty)
|
||||
{
|
||||
Mat cloned;
|
||||
Mat_<Point2f> source(5, 0);
|
||||
|
||||
ASSERT_NO_THROW(cloned = source.clone());
|
||||
}
|
||||
|
||||
@@ -365,3 +365,20 @@ TEST(Core_RNG_MT19937, regression)
|
||||
ASSERT_EQ(expected[i], actual[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Core_Rand, Regression_Stack_Corruption)
|
||||
{
|
||||
int bufsz = 128; //enough for 14 doubles
|
||||
AutoBuffer<uchar> buffer(bufsz);
|
||||
size_t offset = 0;
|
||||
cv::Mat_<cv::Point2d> x(2, 3, (cv::Point2d*)(buffer+offset)); offset += x.total()*x.elemSize();
|
||||
double& param1 = *(double*)(buffer+offset); offset += sizeof(double);
|
||||
double& param2 = *(double*)(buffer+offset); offset += sizeof(double);
|
||||
param1 = -9; param2 = 2;
|
||||
|
||||
cv::theRNG().fill(x, cv::RNG::NORMAL, param1, param2);
|
||||
|
||||
ASSERT_EQ(param1, -9);
|
||||
ASSERT_EQ(param2, 2);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace
|
||||
~FpuControl();
|
||||
|
||||
private:
|
||||
#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__)
|
||||
#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__powerpc64__)
|
||||
fpu_control_t fpu_oldcw, fpu_cw;
|
||||
#elif defined(_WIN32) && !defined(_WIN64)
|
||||
unsigned int fpu_oldcw, fpu_cw;
|
||||
@@ -61,7 +61,7 @@ namespace
|
||||
|
||||
FpuControl::FpuControl()
|
||||
{
|
||||
#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__)
|
||||
#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__powerpc64__)
|
||||
_FPU_GETCW(fpu_oldcw);
|
||||
fpu_cw = (fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_DOUBLE & ~_FPU_SINGLE) | _FPU_SINGLE;
|
||||
_FPU_SETCW(fpu_cw);
|
||||
@@ -74,7 +74,7 @@ namespace
|
||||
|
||||
FpuControl::~FpuControl()
|
||||
{
|
||||
#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__)
|
||||
#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__powerpc64__)
|
||||
_FPU_SETCW(fpu_oldcw);
|
||||
#elif defined(_WIN32) && !defined(_WIN64)
|
||||
_controlfp_s(&fpu_cw, fpu_oldcw, _MCW_PC);
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__)
|
||||
#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__powerpc64__)
|
||||
#include <fpu_control.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -347,13 +347,19 @@ namespace pyrlk
|
||||
template <typename T>
|
||||
struct DenormalizationFactor
|
||||
{
|
||||
static const float factor = 1.0;
|
||||
static __device__ __forceinline__ float factor()
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DenormalizationFactor<uchar>
|
||||
{
|
||||
static const float factor = 255.0;
|
||||
static __device__ __forceinline__ float factor()
|
||||
{
|
||||
return 255.0f;
|
||||
}
|
||||
};
|
||||
|
||||
template <int cn, int PATCH_X, int PATCH_Y, bool calcErr, typename T>
|
||||
@@ -544,7 +550,7 @@ namespace pyrlk
|
||||
nextPts[blockIdx.x] = nextPt;
|
||||
|
||||
if (calcErr)
|
||||
err[blockIdx.x] = static_cast<float>(errval) / (::min(cn, 3) * c_winSize_x * c_winSize_y) * DenormalizationFactor<T>::factor;
|
||||
err[blockIdx.x] = static_cast<float>(errval) / (::min(cn, 3) * c_winSize_x * c_winSize_y) * DenormalizationFactor<T>::factor();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace cv { namespace cuda { namespace device { namespace optflow_farneback
|
||||
|
||||
namespace
|
||||
{
|
||||
class FarnebackOpticalFlowImpl : public FarnebackOpticalFlow
|
||||
class FarnebackOpticalFlowImpl : public cv::cuda::FarnebackOpticalFlow
|
||||
{
|
||||
public:
|
||||
FarnebackOpticalFlowImpl(int numLevels, double pyrScale, bool fastPyramids, int winSize,
|
||||
@@ -459,7 +459,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<FarnebackOpticalFlow> cv::cuda::FarnebackOpticalFlow::create(int numLevels, double pyrScale, bool fastPyramids, int winSize,
|
||||
Ptr<cv::cuda::FarnebackOpticalFlow> cv::cuda::FarnebackOpticalFlow::create(int numLevels, double pyrScale, bool fastPyramids, int winSize,
|
||||
int numIters, int polyN, double polySigma, int flags)
|
||||
{
|
||||
return makePtr<FarnebackOpticalFlowImpl>(numLevels, pyrScale, fastPyramids, winSize,
|
||||
|
||||
@@ -47,9 +47,9 @@ using namespace cv::cuda;
|
||||
|
||||
#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
|
||||
|
||||
Ptr<SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr<SparsePyrLKOpticalFlow>(); }
|
||||
Ptr<cv::cuda::SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr<SparsePyrLKOpticalFlow>(); }
|
||||
|
||||
Ptr<DensePyrLKOpticalFlow> cv::cuda::DensePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr<DensePyrLKOpticalFlow>(); }
|
||||
Ptr<cv::cuda::DensePyrLKOpticalFlow> cv::cuda::DensePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr<DensePyrLKOpticalFlow>(); }
|
||||
|
||||
#else /* !defined (HAVE_CUDA) */
|
||||
|
||||
@@ -283,7 +283,7 @@ namespace
|
||||
vPyr[idx].copyTo(v, stream);
|
||||
}
|
||||
|
||||
class SparsePyrLKOpticalFlowImpl : public SparsePyrLKOpticalFlow, private PyrLKOpticalFlowBase
|
||||
class SparsePyrLKOpticalFlowImpl : public cv::cuda::SparsePyrLKOpticalFlow, private PyrLKOpticalFlowBase
|
||||
{
|
||||
public:
|
||||
SparsePyrLKOpticalFlowImpl(Size winSize, int maxLevel, int iters, bool useInitialFlow) :
|
||||
@@ -366,14 +366,14 @@ namespace
|
||||
};
|
||||
}
|
||||
|
||||
Ptr<SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow)
|
||||
Ptr<cv::cuda::SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow)
|
||||
{
|
||||
return makePtr<SparsePyrLKOpticalFlowImpl>(winSize, maxLevel, iters, useInitialFlow);
|
||||
}
|
||||
|
||||
Ptr<DensePyrLKOpticalFlow> cv::cuda::DensePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow)
|
||||
Ptr<cv::cuda::DensePyrLKOpticalFlow> cv::cuda::DensePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow)
|
||||
{
|
||||
return makePtr<DensePyrLKOpticalFlowImpl>(winSize, maxLevel, iters, useInitialFlow);
|
||||
}
|
||||
|
||||
#endif /* !defined (HAVE_CUDA) */
|
||||
#endif /* !defined (HAVE_CUDA) */
|
||||
|
||||
@@ -342,14 +342,14 @@ void AKAZEFeatures::Find_Scale_Space_Extrema(std::vector<KeyPoint>& kpts)
|
||||
|
||||
if (is_out == false) {
|
||||
if (is_repeated == false) {
|
||||
point.pt.x *= ratio;
|
||||
point.pt.y *= ratio;
|
||||
point.pt.x = (float)(point.pt.x*ratio + .5*(ratio-1.0));
|
||||
point.pt.y = (float)(point.pt.y*ratio + .5*(ratio-1.0));
|
||||
kpts_aux.push_back(point);
|
||||
npoints++;
|
||||
}
|
||||
else {
|
||||
point.pt.x *= ratio;
|
||||
point.pt.y *= ratio;
|
||||
point.pt.x = (float)(point.pt.x*ratio + .5*(ratio-1.0));
|
||||
point.pt.y = (float)(point.pt.y*ratio + .5*(ratio-1.0));
|
||||
kpts_aux[id_repeated] = point;
|
||||
}
|
||||
} // if is_out
|
||||
@@ -439,8 +439,8 @@ void AKAZEFeatures::Do_Subpixel_Refinement(std::vector<KeyPoint>& kpts)
|
||||
kpts[i].pt.x = x + dst(0);
|
||||
kpts[i].pt.y = y + dst(1);
|
||||
int power = fastpow(2, evolution_[kpts[i].class_id].octave);
|
||||
kpts[i].pt.x *= power;
|
||||
kpts[i].pt.y *= power;
|
||||
kpts[i].pt.x = (float)(kpts[i].pt.x*power + .5*(power-1));
|
||||
kpts[i].pt.y = (float)(kpts[i].pt.y*power + .5*(power-1));
|
||||
kpts[i].angle = 0.0;
|
||||
|
||||
// In OpenCV the size of a keypoint its the diameter
|
||||
|
||||
@@ -425,7 +425,7 @@ CV_EXPORTS_W double getWindowProperty(const String& winname, int prop_id);
|
||||
|
||||
@param winname Name of the window.
|
||||
@param onMouse Mouse callback. See OpenCV samples, such as
|
||||
<https://github.com/Itseez/opencv/tree/master/samples/cpp/ffilldemo.cpp>, on how to specify and
|
||||
<https://github.com/opencv/opencv/tree/master/samples/cpp/ffilldemo.cpp>, on how to specify and
|
||||
use the callback.
|
||||
@param userdata The optional parameter passed to the callback.
|
||||
*/
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_QT_OPENGL
|
||||
#ifdef Q_WS_X11
|
||||
#if defined Q_WS_X11 /* Qt4 */ || defined Q_OS_LINUX /* Qt5 */
|
||||
#include <GL/glx.h>
|
||||
#endif
|
||||
#endif
|
||||
@@ -2629,8 +2629,15 @@ void DefaultViewPort::resizeEvent(QResizeEvent* evnt)
|
||||
|
||||
void DefaultViewPort::wheelEvent(QWheelEvent* evnt)
|
||||
{
|
||||
scaleView(evnt->delta() / 240.0, evnt->pos());
|
||||
viewport()->update();
|
||||
int delta = evnt->delta();
|
||||
int cv_event = ((evnt->orientation() == Qt::Vertical) ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL);
|
||||
int flags = (delta & 0xffff)<<16;
|
||||
QPoint pt = evnt->pos();
|
||||
|
||||
icvmouseHandler((QMouseEvent*)evnt, mouse_wheel, cv_event, flags);
|
||||
icvmouseProcessing(QPointF(pt), cv_event, flags);
|
||||
|
||||
QWidget::wheelEvent(evnt);
|
||||
}
|
||||
|
||||
|
||||
@@ -2847,7 +2854,9 @@ void DefaultViewPort::icvmouseHandler(QMouseEvent *evnt, type_mouse_event catego
|
||||
Qt::KeyboardModifiers modifiers = evnt->modifiers();
|
||||
Qt::MouseButtons buttons = evnt->buttons();
|
||||
|
||||
flags = 0;
|
||||
// This line gives excess flags flushing, with it you cannot predefine flags value.
|
||||
// icvmouseHandler called with flags == 0 where it really need.
|
||||
//flags = 0;
|
||||
if(modifiers & Qt::ShiftModifier)
|
||||
flags |= CV_EVENT_FLAG_SHIFTKEY;
|
||||
if(modifiers & Qt::ControlModifier)
|
||||
@@ -2862,23 +2871,24 @@ void DefaultViewPort::icvmouseHandler(QMouseEvent *evnt, type_mouse_event catego
|
||||
if(buttons & Qt::MidButton)
|
||||
flags |= CV_EVENT_FLAG_MBUTTON;
|
||||
|
||||
cv_event = CV_EVENT_MOUSEMOVE;
|
||||
switch(evnt->button())
|
||||
{
|
||||
case Qt::LeftButton:
|
||||
cv_event = tableMouseButtons[category][0];
|
||||
flags |= CV_EVENT_FLAG_LBUTTON;
|
||||
break;
|
||||
case Qt::RightButton:
|
||||
cv_event = tableMouseButtons[category][1];
|
||||
flags |= CV_EVENT_FLAG_RBUTTON;
|
||||
break;
|
||||
case Qt::MidButton:
|
||||
cv_event = tableMouseButtons[category][2];
|
||||
flags |= CV_EVENT_FLAG_MBUTTON;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
if (cv_event == -1)
|
||||
switch(evnt->button())
|
||||
{
|
||||
case Qt::LeftButton:
|
||||
cv_event = tableMouseButtons[category][0];
|
||||
flags |= CV_EVENT_FLAG_LBUTTON;
|
||||
break;
|
||||
case Qt::RightButton:
|
||||
cv_event = tableMouseButtons[category][1];
|
||||
flags |= CV_EVENT_FLAG_RBUTTON;
|
||||
break;
|
||||
case Qt::MidButton:
|
||||
cv_event = tableMouseButtons[category][2];
|
||||
flags |= CV_EVENT_FLAG_MBUTTON;
|
||||
break;
|
||||
default:
|
||||
cv_event = CV_EVENT_MOUSEMOVE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3181,6 +3191,19 @@ void OpenGlViewPort::paintGL()
|
||||
glDrawCallback(glDrawData);
|
||||
}
|
||||
|
||||
void OpenGlViewPort::wheelEvent(QWheelEvent* evnt)
|
||||
{
|
||||
int delta = evnt->delta();
|
||||
int cv_event = ((evnt->orientation() == Qt::Vertical) ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL);
|
||||
int flags = (delta & 0xffff)<<16;
|
||||
QPoint pt = evnt->pos();
|
||||
|
||||
icvmouseHandler((QMouseEvent*)evnt, mouse_wheel, cv_event, flags);
|
||||
icvmouseProcessing(QPointF(pt), cv_event, flags);
|
||||
|
||||
QWidget::wheelEvent(evnt);
|
||||
}
|
||||
|
||||
void OpenGlViewPort::mousePressEvent(QMouseEvent* evnt)
|
||||
{
|
||||
int cv_event = -1, flags = 0;
|
||||
@@ -3234,42 +3257,41 @@ void OpenGlViewPort::icvmouseHandler(QMouseEvent* evnt, type_mouse_event categor
|
||||
Qt::KeyboardModifiers modifiers = evnt->modifiers();
|
||||
Qt::MouseButtons buttons = evnt->buttons();
|
||||
|
||||
flags = 0;
|
||||
if (modifiers & Qt::ShiftModifier)
|
||||
// This line gives excess flags flushing, with it you cannot predefine flags value.
|
||||
// icvmouseHandler called with flags == 0 where it really need.
|
||||
//flags = 0;
|
||||
if(modifiers & Qt::ShiftModifier)
|
||||
flags |= CV_EVENT_FLAG_SHIFTKEY;
|
||||
if (modifiers & Qt::ControlModifier)
|
||||
if(modifiers & Qt::ControlModifier)
|
||||
flags |= CV_EVENT_FLAG_CTRLKEY;
|
||||
if (modifiers & Qt::AltModifier)
|
||||
if(modifiers & Qt::AltModifier)
|
||||
flags |= CV_EVENT_FLAG_ALTKEY;
|
||||
|
||||
if (buttons & Qt::LeftButton)
|
||||
if(buttons & Qt::LeftButton)
|
||||
flags |= CV_EVENT_FLAG_LBUTTON;
|
||||
if (buttons & Qt::RightButton)
|
||||
if(buttons & Qt::RightButton)
|
||||
flags |= CV_EVENT_FLAG_RBUTTON;
|
||||
if (buttons & Qt::MidButton)
|
||||
if(buttons & Qt::MidButton)
|
||||
flags |= CV_EVENT_FLAG_MBUTTON;
|
||||
|
||||
cv_event = CV_EVENT_MOUSEMOVE;
|
||||
switch (evnt->button())
|
||||
{
|
||||
case Qt::LeftButton:
|
||||
cv_event = tableMouseButtons[category][0];
|
||||
flags |= CV_EVENT_FLAG_LBUTTON;
|
||||
break;
|
||||
|
||||
case Qt::RightButton:
|
||||
cv_event = tableMouseButtons[category][1];
|
||||
flags |= CV_EVENT_FLAG_RBUTTON;
|
||||
break;
|
||||
|
||||
case Qt::MidButton:
|
||||
cv_event = tableMouseButtons[category][2];
|
||||
flags |= CV_EVENT_FLAG_MBUTTON;
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
if (cv_event == -1)
|
||||
switch(evnt->button())
|
||||
{
|
||||
case Qt::LeftButton:
|
||||
cv_event = tableMouseButtons[category][0];
|
||||
flags |= CV_EVENT_FLAG_LBUTTON;
|
||||
break;
|
||||
case Qt::RightButton:
|
||||
cv_event = tableMouseButtons[category][1];
|
||||
flags |= CV_EVENT_FLAG_RBUTTON;
|
||||
break;
|
||||
case Qt::MidButton:
|
||||
cv_event = tableMouseButtons[category][2];
|
||||
flags |= CV_EVENT_FLAG_MBUTTON;
|
||||
break;
|
||||
default:
|
||||
cv_event = CV_EVENT_MOUSEMOVE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -366,12 +366,13 @@ private slots:
|
||||
};
|
||||
|
||||
|
||||
enum type_mouse_event { mouse_up = 0, mouse_down = 1, mouse_dbclick = 2, mouse_move = 3 };
|
||||
enum type_mouse_event { mouse_up = 0, mouse_down = 1, mouse_dbclick = 2, mouse_move = 3, mouse_wheel = 4 };
|
||||
static const int tableMouseButtons[][3]={
|
||||
{CV_EVENT_LBUTTONUP, CV_EVENT_RBUTTONUP, CV_EVENT_MBUTTONUP}, //mouse_up
|
||||
{CV_EVENT_LBUTTONDOWN, CV_EVENT_RBUTTONDOWN, CV_EVENT_MBUTTONDOWN}, //mouse_down
|
||||
{CV_EVENT_LBUTTONDBLCLK, CV_EVENT_RBUTTONDBLCLK, CV_EVENT_MBUTTONDBLCLK}, //mouse_dbclick
|
||||
{CV_EVENT_MOUSEMOVE, CV_EVENT_MOUSEMOVE, CV_EVENT_MOUSEMOVE} //mouse_move
|
||||
{CV_EVENT_MOUSEMOVE, CV_EVENT_MOUSEMOVE, CV_EVENT_MOUSEMOVE}, //mouse_move
|
||||
{0, 0, 0} //mouse_wheel, to prevent exceptions in code
|
||||
};
|
||||
|
||||
|
||||
@@ -436,6 +437,7 @@ protected:
|
||||
void resizeGL(int w, int h);
|
||||
void paintGL();
|
||||
|
||||
void wheelEvent(QWheelEvent* event);
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void mouseReleaseEvent(QMouseEvent* event);
|
||||
|
||||
@@ -52,8 +52,11 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#if (GTK_MAJOR_VERSION == 3)
|
||||
#define GTK_VERSION3
|
||||
#define GTK_VERSION3 1
|
||||
#endif //GTK_MAJOR_VERSION >= 3
|
||||
#if (GTK_MAJOR_VERSION > 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 4))
|
||||
#define GTK_VERSION3_4 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENGL
|
||||
#include <gtk/gtkgl.h>
|
||||
@@ -61,6 +64,13 @@
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#ifndef BIT_ALLIN
|
||||
#define BIT_ALLIN(x,y) ( ((x)&(y)) == (y) )
|
||||
#endif
|
||||
#ifndef BIT_MAP
|
||||
#define BIT_MAP(x,y,z) ( ((x)&(y)) ? (z) : 0 )
|
||||
#endif
|
||||
|
||||
// TODO Fix the initial window size when flags=0. Right now the initial window is by default
|
||||
// 320x240 size. A better default would be actual size of the image. Problem
|
||||
// is determining desired window size with trackbars while still allowing resizing.
|
||||
@@ -1006,6 +1016,7 @@ CV_IMPL int cvNamedWindow( const char* name, int flags )
|
||||
|
||||
CvWindow* window;
|
||||
int len;
|
||||
int b_nautosize;
|
||||
|
||||
cvInitSystem(1,(char**)&name);
|
||||
if( !name )
|
||||
@@ -1066,6 +1077,8 @@ CV_IMPL int cvNamedWindow( const char* name, int flags )
|
||||
G_CALLBACK(icvOnMouse), window );
|
||||
g_signal_connect( window->widget, "motion-notify-event",
|
||||
G_CALLBACK(icvOnMouse), window );
|
||||
g_signal_connect( window->widget, "scroll-event",
|
||||
G_CALLBACK(icvOnMouse), window );
|
||||
g_signal_connect( window->frame, "delete-event",
|
||||
G_CALLBACK(icvOnClose), window );
|
||||
#if defined(GTK_VERSION3)
|
||||
@@ -1076,7 +1089,12 @@ CV_IMPL int cvNamedWindow( const char* name, int flags )
|
||||
G_CALLBACK(cvImageWidget_expose), window );
|
||||
#endif //GTK_VERSION3
|
||||
|
||||
gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK) ;
|
||||
|
||||
#if defined(GTK_VERSION3_4)
|
||||
gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK) ;
|
||||
#else
|
||||
gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK) ;
|
||||
#endif //GTK_VERSION3_4
|
||||
|
||||
gtk_widget_show( window->frame );
|
||||
gtk_window_set_title( GTK_WINDOW(window->frame), name );
|
||||
@@ -1085,11 +1103,11 @@ CV_IMPL int cvNamedWindow( const char* name, int flags )
|
||||
hg_windows->prev = window;
|
||||
hg_windows = window;
|
||||
|
||||
gtk_window_set_resizable( GTK_WINDOW(window->frame), (flags & CV_WINDOW_AUTOSIZE) == 0 );
|
||||
|
||||
b_nautosize = ((flags & CV_WINDOW_AUTOSIZE) == 0);
|
||||
gtk_window_set_resizable( GTK_WINDOW(window->frame), b_nautosize );
|
||||
|
||||
// allow window to be resized
|
||||
if( (flags & CV_WINDOW_AUTOSIZE)==0 ){
|
||||
if( b_nautosize ){
|
||||
GdkGeometry geometry;
|
||||
geometry.min_width = 50;
|
||||
geometry.min_height = 50;
|
||||
@@ -1817,7 +1835,7 @@ static gboolean icvOnKeyPress(GtkWidget* widget, GdkEventKey* event, gpointer us
|
||||
{
|
||||
int code = 0;
|
||||
|
||||
if ( (event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK && (event->keyval == GDK_s || event->keyval == GDK_S))
|
||||
if ( BIT_ALLIN(event->state, GDK_CONTROL_MASK) && (event->keyval == GDK_s || event->keyval == GDK_S))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1901,7 +1919,7 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da
|
||||
CvWindow* window = (CvWindow*)user_data;
|
||||
CvPoint2D32f pt32f(-1., -1.);
|
||||
CvPoint pt(-1,-1);
|
||||
int cv_event = -1, state = 0;
|
||||
int cv_event = -1, state = 0, flags = 0;
|
||||
CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
|
||||
|
||||
if( window->signature != CV_WINDOW_MAGIC_VAL ||
|
||||
@@ -1947,12 +1965,40 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da
|
||||
}
|
||||
state = event_button->state;
|
||||
}
|
||||
else if( event->type == GDK_SCROLL )
|
||||
{
|
||||
#if defined(GTK_VERSION3_4)
|
||||
// NOTE: in current implementation doesn't possible to put into callback function delta_x and delta_y separetely
|
||||
double delta = (event->scroll.delta_x + event->scroll.delta_y);
|
||||
cv_event = (event->scroll.delta_y!=0) ? CV_EVENT_MOUSEHWHEEL : CV_EVENT_MOUSEWHEEL;
|
||||
#else
|
||||
cv_event = CV_EVENT_MOUSEWHEEL;
|
||||
#endif //GTK_VERSION3_4
|
||||
|
||||
if( cv_event >= 0 ){
|
||||
state = event->scroll.state;
|
||||
|
||||
switch(event->scroll.direction) {
|
||||
#if defined(GTK_VERSION3_4)
|
||||
case GDK_SCROLL_SMOOTH: flags |= (((int)delta << 16));
|
||||
break;
|
||||
#endif //GTK_VERSION3_4
|
||||
case GDK_SCROLL_LEFT: cv_event = CV_EVENT_MOUSEHWHEEL;
|
||||
case GDK_SCROLL_UP: flags |= ((-(int)1 << 16));
|
||||
break;
|
||||
case GDK_SCROLL_RIGHT: cv_event = CV_EVENT_MOUSEHWHEEL;
|
||||
case GDK_SCROLL_DOWN: flags |= (((int)1 << 16));
|
||||
break;
|
||||
default: ;
|
||||
};
|
||||
}
|
||||
|
||||
if( cv_event >= 0 )
|
||||
{
|
||||
// scale point if image is scaled
|
||||
if( (image_widget->flags & CV_WINDOW_AUTOSIZE)==0 &&
|
||||
image_widget->original_image &&
|
||||
image_widget->scaled_image ){
|
||||
image_widget->scaled_image )
|
||||
{
|
||||
// image origin is not necessarily at (0,0)
|
||||
#if defined (GTK_VERSION3)
|
||||
int x0 = (gtk_widget_get_allocated_width(widget) - image_widget->scaled_image->cols)/2;
|
||||
@@ -1966,25 +2012,27 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da
|
||||
pt.y = cvFloor( ((pt32f.y-y0)*image_widget->original_image->rows)/
|
||||
image_widget->scaled_image->rows );
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
pt = cvPointFrom32f( pt32f );
|
||||
}
|
||||
|
||||
// if((unsigned)pt.x < (unsigned)(image_widget->original_image->width) &&
|
||||
// (unsigned)pt.y < (unsigned)(image_widget->original_image->height) )
|
||||
{
|
||||
int flags = (state & GDK_SHIFT_MASK ? CV_EVENT_FLAG_SHIFTKEY : 0) |
|
||||
(state & GDK_CONTROL_MASK ? CV_EVENT_FLAG_CTRLKEY : 0) |
|
||||
(state & (GDK_MOD1_MASK|GDK_MOD2_MASK) ? CV_EVENT_FLAG_ALTKEY : 0) |
|
||||
(state & GDK_BUTTON1_MASK ? CV_EVENT_FLAG_LBUTTON : 0) |
|
||||
(state & GDK_BUTTON2_MASK ? CV_EVENT_FLAG_MBUTTON : 0) |
|
||||
(state & GDK_BUTTON3_MASK ? CV_EVENT_FLAG_RBUTTON : 0);
|
||||
flags |= BIT_MAP(state, GDK_SHIFT_MASK, CV_EVENT_FLAG_SHIFTKEY) |
|
||||
BIT_MAP(state, GDK_CONTROL_MASK, CV_EVENT_FLAG_CTRLKEY) |
|
||||
BIT_MAP(state, GDK_MOD1_MASK, CV_EVENT_FLAG_ALTKEY) |
|
||||
BIT_MAP(state, GDK_MOD2_MASK, CV_EVENT_FLAG_ALTKEY) |
|
||||
BIT_MAP(state, GDK_BUTTON1_MASK, CV_EVENT_FLAG_LBUTTON) |
|
||||
BIT_MAP(state, GDK_BUTTON2_MASK, CV_EVENT_FLAG_MBUTTON) |
|
||||
BIT_MAP(state, GDK_BUTTON3_MASK, CV_EVENT_FLAG_RBUTTON);
|
||||
window->on_mouse( cv_event, pt.x, pt.y, flags, window->on_mouse_param );
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean icvAlarm( gpointer user_data )
|
||||
|
||||
@@ -35,6 +35,11 @@ if(HAVE_PNG)
|
||||
list(APPEND GRFMT_LIBS ${PNG_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(HAVE_GDCM)
|
||||
ocv_include_directories(${GDCM_INCLUDE_DIRS})
|
||||
list(APPEND GRFMT_LIBS ${GDCM_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(HAVE_TIFF)
|
||||
ocv_include_directories(${TIFF_INCLUDE_DIR})
|
||||
list(APPEND GRFMT_LIBS ${TIFF_LIBRARIES})
|
||||
@@ -57,6 +62,7 @@ endif()
|
||||
|
||||
file(GLOB grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/grfmt*.hpp)
|
||||
file(GLOB grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/grfmt*.cpp)
|
||||
|
||||
list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.hpp)
|
||||
list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.cpp)
|
||||
list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.hpp)
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and 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 the Intel Corporation or 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "grfmt_gdcm.hpp"
|
||||
|
||||
#ifdef HAVE_GDCM
|
||||
|
||||
//#define DBG(...) printf(__VA_ARGS__)
|
||||
#define DBG(...)
|
||||
|
||||
#include <gdcmImageReader.h>
|
||||
|
||||
static const size_t preamble_skip = 128;
|
||||
static const size_t magic_len = 4;
|
||||
|
||||
inline cv::String getMagic()
|
||||
{
|
||||
return cv::String("\x44\x49\x43\x4D", 4);
|
||||
}
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
/************************ DICOM decoder *****************************/
|
||||
|
||||
DICOMDecoder::DICOMDecoder()
|
||||
{
|
||||
// DICOM preamble is 128 bytes (can have any value, defaults to 0) + 4 bytes magic number (DICM)
|
||||
m_signature = String(preamble_skip, (char)'\x0') + getMagic();
|
||||
m_buf_supported = false;
|
||||
}
|
||||
|
||||
bool DICOMDecoder::checkSignature( const String& signature ) const
|
||||
{
|
||||
if (signature.size() >= preamble_skip + magic_len)
|
||||
{
|
||||
if (signature.substr(preamble_skip, magic_len) == getMagic())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
DBG("GDCM | Signature does not match\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageDecoder DICOMDecoder::newDecoder() const
|
||||
{
|
||||
return makePtr<DICOMDecoder>();
|
||||
}
|
||||
|
||||
bool DICOMDecoder::readHeader()
|
||||
{
|
||||
gdcm::ImageReader csImageReader;
|
||||
csImageReader.SetFileName(m_filename.c_str());
|
||||
if(!csImageReader.Read())
|
||||
{
|
||||
DBG("GDCM | Failed to open DICOM file\n");
|
||||
return(false);
|
||||
}
|
||||
|
||||
const gdcm::Image &csImage = csImageReader.GetImage();
|
||||
bool bOK = true;
|
||||
switch (csImage.GetPhotometricInterpretation().GetType())
|
||||
{
|
||||
case gdcm::PhotometricInterpretation::MONOCHROME1:
|
||||
case gdcm::PhotometricInterpretation::MONOCHROME2:
|
||||
{
|
||||
switch (csImage.GetPixelFormat().GetScalarType())
|
||||
{
|
||||
case gdcm::PixelFormat::INT8: m_type = CV_8SC1; break;
|
||||
case gdcm::PixelFormat::UINT8: m_type = CV_8UC1; break;
|
||||
case gdcm::PixelFormat::INT16: m_type = CV_16SC1; break;
|
||||
case gdcm::PixelFormat::UINT16: m_type = CV_16UC1; break;
|
||||
case gdcm::PixelFormat::INT32: m_type = CV_32SC1; break;
|
||||
case gdcm::PixelFormat::FLOAT32: m_type = CV_32FC1; break;
|
||||
case gdcm::PixelFormat::FLOAT64: m_type = CV_64FC1; break;
|
||||
default: bOK = false; DBG("GDCM | Monochrome scalar type not supported\n"); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case gdcm::PhotometricInterpretation::RGB:
|
||||
{
|
||||
switch (csImage.GetPixelFormat().GetScalarType())
|
||||
{
|
||||
case gdcm::PixelFormat::UINT8: m_type = CV_8UC3; break;
|
||||
default: bOK = false; DBG("GDCM | RGB scalar type not supported\n"); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
bOK = false;
|
||||
DBG("GDCM | PI not supported: %s\n", csImage.GetPhotometricInterpretation().GetString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(bOK)
|
||||
{
|
||||
unsigned int ndim = csImage.GetNumberOfDimensions();
|
||||
if (ndim != 2)
|
||||
{
|
||||
DBG("GDCM | Invalid dimensions number: %d\n", ndim);
|
||||
bOK = false;
|
||||
}
|
||||
}
|
||||
if (bOK)
|
||||
{
|
||||
const unsigned int *piDimension = csImage.GetDimensions();
|
||||
m_height = piDimension[0];
|
||||
m_width = piDimension[1];
|
||||
if( ( m_width <=0 ) || ( m_height <=0 ) )
|
||||
{
|
||||
DBG("GDCM | Invalid dimensions: %d x %d\n", piDimension[0], piDimension[1]);
|
||||
bOK = false;
|
||||
}
|
||||
}
|
||||
|
||||
return(bOK);
|
||||
}
|
||||
|
||||
|
||||
bool DICOMDecoder::readData( Mat& csImage )
|
||||
{
|
||||
csImage.create(m_width,m_height,m_type);
|
||||
|
||||
gdcm::ImageReader csImageReader;
|
||||
csImageReader.SetFileName(m_filename.c_str());
|
||||
if(!csImageReader.Read())
|
||||
{
|
||||
DBG("GDCM | Failed to Read\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const gdcm::Image &img = csImageReader.GetImage();
|
||||
|
||||
unsigned long len = img.GetBufferLength();
|
||||
if (len > csImage.elemSize() * csImage.total())
|
||||
{
|
||||
DBG("GDCM | Buffer is bigger than Mat: %ld > %ld * %ld\n", len, csImage.elemSize(), csImage.total());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!img.GetBuffer((char*)csImage.ptr()))
|
||||
{
|
||||
DBG("GDCM | Failed to GetBuffer\n");
|
||||
return false;
|
||||
}
|
||||
DBG("GDCM | Read OK\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // HAVE_GDCM
|
||||
@@ -0,0 +1,70 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and 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 the Intel Corporation or 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef _GDCM_DICOM_H_
|
||||
#define _GDCM_DICOM_H_
|
||||
|
||||
#include "cvconfig.h"
|
||||
|
||||
#ifdef HAVE_GDCM
|
||||
|
||||
#include "grfmt_base.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
// DICOM image reader using GDCM
|
||||
class DICOMDecoder : public BaseImageDecoder
|
||||
{
|
||||
public:
|
||||
DICOMDecoder();
|
||||
bool readData( Mat& img );
|
||||
bool readHeader();
|
||||
ImageDecoder newDecoder() const;
|
||||
virtual bool checkSignature( const String& signature ) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // HAVE_GDCM
|
||||
|
||||
#endif/*_GDCM_DICOM_H_*/
|
||||
@@ -190,16 +190,14 @@ bool PngDecoder::readHeader()
|
||||
switch(color_type)
|
||||
{
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
m_type = CV_8UC3;
|
||||
break;
|
||||
case PNG_COLOR_TYPE_PALETTE:
|
||||
png_get_tRNS( png_ptr, info_ptr, &trans, &num_trans, &trans_values);
|
||||
//Check if there is a transparency value in the palette
|
||||
if ( num_trans > 0 )
|
||||
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values);
|
||||
if( num_trans > 0 )
|
||||
m_type = CV_8UC4;
|
||||
else
|
||||
m_type = CV_8UC3;
|
||||
break;
|
||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
m_type = CV_8UC4;
|
||||
break;
|
||||
@@ -255,12 +253,13 @@ bool PngDecoder::readData( Mat& img )
|
||||
* stripping alpha.. 18.11.2004 Axel Walthelm
|
||||
*/
|
||||
png_set_strip_alpha( png_ptr );
|
||||
}
|
||||
} else
|
||||
png_set_tRNS_to_alpha( png_ptr );
|
||||
|
||||
if( m_color_type == PNG_COLOR_TYPE_PALETTE )
|
||||
png_set_palette_to_rgb( png_ptr );
|
||||
|
||||
if( m_color_type == PNG_COLOR_TYPE_GRAY && m_bit_depth < 8 )
|
||||
if( (m_color_type & PNG_COLOR_MASK_COLOR) == 0 && m_bit_depth < 8 )
|
||||
#if (PNG_LIBPNG_VER_MAJOR*10000 + PNG_LIBPNG_VER_MINOR*100 + PNG_LIBPNG_VER_RELEASE >= 10209) || \
|
||||
(PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR == 0 && PNG_LIBPNG_VER_RELEASE >= 18)
|
||||
png_set_expand_gray_1_2_4_to_8( png_ptr );
|
||||
@@ -268,7 +267,7 @@ bool PngDecoder::readData( Mat& img )
|
||||
png_set_gray_1_2_4_to_8( png_ptr );
|
||||
#endif
|
||||
|
||||
if( CV_MAT_CN(m_type) > 1 && color )
|
||||
if( (m_color_type & PNG_COLOR_MASK_COLOR) && color )
|
||||
png_set_bgr( png_ptr ); // convert RGB to BGR
|
||||
else if( color )
|
||||
png_set_gray_to_rgb( png_ptr ); // Gray->RGB
|
||||
|
||||
@@ -54,5 +54,6 @@
|
||||
#include "grfmt_webp.hpp"
|
||||
#include "grfmt_hdr.hpp"
|
||||
#include "grfmt_gdal.hpp"
|
||||
#include "grfmt_gdcm.hpp"
|
||||
|
||||
#endif/*_GRFMTS_H_*/
|
||||
|
||||
@@ -93,6 +93,9 @@ struct ImageCodecInitializer
|
||||
decoders.push_back( makePtr<PngDecoder>() );
|
||||
encoders.push_back( makePtr<PngEncoder>() );
|
||||
#endif
|
||||
#ifdef HAVE_GDCM
|
||||
decoders.push_back( makePtr<DICOMDecoder>() );
|
||||
#endif
|
||||
#ifdef HAVE_JASPER
|
||||
decoders.push_back( makePtr<Jpeg2KDecoder>() );
|
||||
encoders.push_back( makePtr<Jpeg2KEncoder>() );
|
||||
|
||||
@@ -1664,6 +1664,19 @@ CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,
|
||||
double threshold1, double threshold2,
|
||||
int apertureSize = 3, bool L2gradient = false );
|
||||
|
||||
/** \overload
|
||||
|
||||
Finds edges in an image using the Canny algorithm with custom image gradient.
|
||||
|
||||
@param dx 16-bit x derivative of input image (CV_16SC1 or CV_16SC3).
|
||||
@param dy 16-bit y derivative of input image (same type as dx).
|
||||
@param edges,threshold1,threshold2,L2gradient See cv::Canny
|
||||
*/
|
||||
CV_EXPORTS_W void Canny( InputArray dx, InputArray dy,
|
||||
OutputArray edges,
|
||||
double threshold1, double threshold2,
|
||||
bool L2gradient = false );
|
||||
|
||||
/** @brief Calculates the minimal eigenvalue of gradient matrices for corner detection.
|
||||
|
||||
The function is similar to cornerEigenValsAndVecs but it calculates and stores only the minimal
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+140
-56
@@ -43,6 +43,10 @@
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels_imgproc.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable: 4127 ) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700)
|
||||
#define USE_IPP_CANNY 1
|
||||
@@ -53,53 +57,73 @@
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
static void CannyImpl(Mat& dx_, Mat& dy_, Mat& _dst, double low_thresh, double high_thresh, bool L2gradient);
|
||||
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high)
|
||||
template <bool useCustomDeriv>
|
||||
static bool ippCanny(const Mat& _src, const Mat& dx_, const Mat& dy_, Mat& _dst, float low, float high)
|
||||
{
|
||||
#if USE_IPP_CANNY
|
||||
int size = 0, size1 = 0;
|
||||
IppiSize roi = { _src.cols, _src.rows };
|
||||
|
||||
if (ippiCannyGetSize(roi, &size) < 0)
|
||||
return false;
|
||||
|
||||
if (!useCustomDeriv)
|
||||
{
|
||||
#if IPP_VERSION_X100 < 900
|
||||
if (ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size) < 0)
|
||||
return false;
|
||||
if (ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size1) < 0)
|
||||
return false;
|
||||
if (ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size1) < 0)
|
||||
return false;
|
||||
size = std::max(size, size1);
|
||||
if (ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size1) < 0)
|
||||
return false;
|
||||
#else
|
||||
if (ippiFilterSobelNegVertBorderGetBufferSize(roi, ippMskSize3x3, ipp8u, ipp16s, 1, &size) < 0)
|
||||
return false;
|
||||
if (ippiFilterSobelHorizBorderGetBufferSize(roi, ippMskSize3x3, ipp8u, ipp16s, 1, &size1) < 0)
|
||||
return false;
|
||||
if (ippiFilterSobelNegVertBorderGetBufferSize(roi, ippMskSize3x3, ipp8u, ipp16s, 1, &size1) < 0)
|
||||
return false;
|
||||
size = std::max(size, size1);
|
||||
if (ippiFilterSobelHorizBorderGetBufferSize(roi, ippMskSize3x3, ipp8u, ipp16s, 1, &size1) < 0)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
size = std::max(size, size1);
|
||||
|
||||
if (ippiCannyGetSize(roi, &size1) < 0)
|
||||
return false;
|
||||
size = std::max(size, size1);
|
||||
size = std::max(size, size1);
|
||||
}
|
||||
|
||||
AutoBuffer<uchar> buf(size + 64);
|
||||
uchar* buffer = alignPtr((uchar*)buf, 32);
|
||||
|
||||
Mat _dx(_src.rows, _src.cols, CV_16S);
|
||||
if( ippiFilterSobelNegVertBorder_8u16s_C1R(_src.ptr(), (int)_src.step,
|
||||
_dx.ptr<short>(), (int)_dx.step, roi,
|
||||
ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 )
|
||||
return false;
|
||||
Mat dx, dy;
|
||||
if (!useCustomDeriv)
|
||||
{
|
||||
Mat _dx(_src.rows, _src.cols, CV_16S);
|
||||
if( ippiFilterSobelNegVertBorder_8u16s_C1R(_src.ptr(), (int)_src.step,
|
||||
_dx.ptr<short>(), (int)_dx.step, roi,
|
||||
ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 )
|
||||
return false;
|
||||
|
||||
Mat _dy(_src.rows, _src.cols, CV_16S);
|
||||
if( ippiFilterSobelHorizBorder_8u16s_C1R(_src.ptr(), (int)_src.step,
|
||||
_dy.ptr<short>(), (int)_dy.step, roi,
|
||||
ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 )
|
||||
return false;
|
||||
Mat _dy(_src.rows, _src.cols, CV_16S);
|
||||
if( ippiFilterSobelHorizBorder_8u16s_C1R(_src.ptr(), (int)_src.step,
|
||||
_dy.ptr<short>(), (int)_dy.step, roi,
|
||||
ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 )
|
||||
return false;
|
||||
|
||||
if( ippiCanny_16s8u_C1R(_dx.ptr<short>(), (int)_dx.step,
|
||||
_dy.ptr<short>(), (int)_dy.step,
|
||||
swap(dx, _dx);
|
||||
swap(dy, _dy);
|
||||
}
|
||||
else
|
||||
{
|
||||
dx = dx_;
|
||||
dy = dy_;
|
||||
}
|
||||
|
||||
if( ippiCanny_16s8u_C1R(dx.ptr<short>(), (int)dx.step,
|
||||
dy.ptr<short>(), (int)dy.step,
|
||||
_dst.ptr(), (int)_dst.step, roi, low, high, buffer) < 0 )
|
||||
return false;
|
||||
return true;
|
||||
#else
|
||||
CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(low); CV_UNUSED(high);
|
||||
CV_UNUSED(_src); CV_UNUSED(dx_); CV_UNUSED(dy_); CV_UNUSED(_dst); CV_UNUSED(low); CV_UNUSED(high);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -107,7 +131,8 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high)
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float high_thresh,
|
||||
template <bool useCustomDeriv>
|
||||
static bool ocl_Canny(InputArray _src, const UMat& dx_, const UMat& dy_, OutputArray _dst, float low_thresh, float high_thresh,
|
||||
int aperture_size, bool L2gradient, int cn, const Size & size)
|
||||
{
|
||||
UMat map;
|
||||
@@ -140,7 +165,8 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float
|
||||
}
|
||||
int low = cvFloor(low_thresh), high = cvFloor(high_thresh);
|
||||
|
||||
if (aperture_size == 3 && !_src.isSubmatrix())
|
||||
if (!useCustomDeriv &&
|
||||
aperture_size == 3 && !_src.isSubmatrix())
|
||||
{
|
||||
/*
|
||||
stage1_with_sobel:
|
||||
@@ -181,8 +207,16 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float
|
||||
Double thresholding
|
||||
*/
|
||||
UMat dx, dy;
|
||||
Sobel(_src, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
Sobel(_src, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
if (!useCustomDeriv)
|
||||
{
|
||||
Sobel(_src, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
Sobel(_src, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
dx = dx_;
|
||||
dy = dy_;
|
||||
}
|
||||
|
||||
ocl::Kernel without_sobel("stage1_without_sobel", ocl::imgproc::canny_oclsrc,
|
||||
format("-D WITHOUT_SOBEL -D cn=%d -D GRP_SIZEX=%d -D GRP_SIZEY=%d%s",
|
||||
@@ -585,9 +619,7 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace cv
|
||||
|
||||
void cv::Canny( InputArray _src, OutputArray _dst,
|
||||
void Canny( InputArray _src, OutputArray _dst,
|
||||
double low_thresh, double high_thresh,
|
||||
int aperture_size, bool L2gradient )
|
||||
{
|
||||
@@ -611,7 +643,7 @@ void cv::Canny( InputArray _src, OutputArray _dst,
|
||||
std::swap(low_thresh, high_thresh);
|
||||
|
||||
CV_OCL_RUN(_dst.isUMat() && (cn == 1 || cn == 3),
|
||||
ocl_Canny(_src, _dst, (float)low_thresh, (float)high_thresh, aperture_size, L2gradient, cn, size))
|
||||
ocl_Canny<false>(_src, UMat(), UMat(), _dst, (float)low_thresh, (float)high_thresh, aperture_size, L2gradient, cn, size))
|
||||
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
|
||||
@@ -620,7 +652,7 @@ void cv::Canny( InputArray _src, OutputArray _dst,
|
||||
return;
|
||||
#endif
|
||||
|
||||
CV_IPP_RUN(USE_IPP_CANNY && (aperture_size == 3 && !L2gradient && 1 == cn), ippCanny(src, dst, (float)low_thresh, (float)high_thresh))
|
||||
CV_IPP_RUN(USE_IPP_CANNY && (aperture_size == 3 && !L2gradient && 1 == cn), ippCanny<false>(src, Mat(), Mat(), dst, (float)low_thresh, (float)high_thresh))
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
|
||||
@@ -683,14 +715,66 @@ while (borderPeaks.try_pop(m))
|
||||
if (!m[mapstep+1]) CANNY_PUSH_SERIAL(m + mapstep + 1);
|
||||
}
|
||||
|
||||
#else
|
||||
// the final pass, form the final image
|
||||
const uchar* pmap = map + mapstep + 1;
|
||||
uchar* pdst = dst.ptr();
|
||||
for (int i = 0; i < src.rows; i++, pmap += mapstep, pdst += dst.step)
|
||||
{
|
||||
for (int j = 0; j < src.cols; j++)
|
||||
pdst[j] = (uchar)-(pmap[j] >> 1);
|
||||
}
|
||||
|
||||
#else
|
||||
Mat dx(src.rows, src.cols, CV_16SC(cn));
|
||||
Mat dy(src.rows, src.cols, CV_16SC(cn));
|
||||
|
||||
Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
|
||||
CannyImpl(dx, dy, dst, low_thresh, high_thresh, L2gradient);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Canny( InputArray _dx, InputArray _dy, OutputArray _dst,
|
||||
double low_thresh, double high_thresh,
|
||||
bool L2gradient )
|
||||
{
|
||||
CV_Assert(_dx.dims() == 2);
|
||||
CV_Assert(_dx.type() == CV_16SC1 || _dx.type() == CV_16SC3);
|
||||
CV_Assert(_dy.type() == _dx.type());
|
||||
CV_Assert(_dx.sameSize(_dy));
|
||||
|
||||
if (low_thresh > high_thresh)
|
||||
std::swap(low_thresh, high_thresh);
|
||||
|
||||
const int cn = _dx.channels();
|
||||
const Size size = _dx.size();
|
||||
|
||||
CV_OCL_RUN(_dst.isUMat(),
|
||||
ocl_Canny<true>(UMat(), _dx.getUMat(), _dy.getUMat(), _dst, (float)low_thresh, (float)high_thresh, 0, L2gradient, cn, size))
|
||||
|
||||
_dst.create(size, CV_8U);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
Mat dx = _dx.getMat();
|
||||
Mat dy = _dy.getMat();
|
||||
|
||||
CV_IPP_RUN(USE_IPP_CANNY && (!L2gradient && 1 == cn), ippCanny<true>(Mat(), dx, dy, dst, (float)low_thresh, (float)high_thresh))
|
||||
|
||||
if (cn > 1)
|
||||
{
|
||||
dx = dx.clone();
|
||||
dy = dy.clone();
|
||||
}
|
||||
CannyImpl(dx, dy, dst, low_thresh, high_thresh, L2gradient);
|
||||
}
|
||||
|
||||
static void CannyImpl(Mat& dx, Mat& dy, Mat& dst,
|
||||
double low_thresh, double high_thresh, bool L2gradient)
|
||||
{
|
||||
const int cn = dx.channels();
|
||||
const int cols = dx.cols, rows = dx.rows;
|
||||
|
||||
if (L2gradient)
|
||||
{
|
||||
low_thresh = std::min(32767.0, low_thresh);
|
||||
@@ -702,8 +786,8 @@ while (borderPeaks.try_pop(m))
|
||||
int low = cvFloor(low_thresh);
|
||||
int high = cvFloor(high_thresh);
|
||||
|
||||
ptrdiff_t mapstep = src.cols + 2;
|
||||
AutoBuffer<uchar> buffer((src.cols+2)*(src.rows+2) + cn * mapstep * 3 * sizeof(int));
|
||||
ptrdiff_t mapstep = cols + 2;
|
||||
AutoBuffer<uchar> buffer((cols+2)*(rows+2) + cn * mapstep * 3 * sizeof(int));
|
||||
|
||||
int* mag_buf[3];
|
||||
mag_buf[0] = (int*)(uchar*)buffer;
|
||||
@@ -713,9 +797,9 @@ while (borderPeaks.try_pop(m))
|
||||
|
||||
uchar* map = (uchar*)(mag_buf[2] + mapstep*cn);
|
||||
memset(map, 1, mapstep);
|
||||
memset(map + mapstep*(src.rows + 1), 1, mapstep);
|
||||
memset(map + mapstep*(rows + 1), 1, mapstep);
|
||||
|
||||
int maxsize = std::max(1 << 10, src.cols * src.rows / 10);
|
||||
int maxsize = std::max(1 << 10, cols * rows / 10);
|
||||
std::vector<uchar*> stack(maxsize);
|
||||
uchar **stack_top = &stack[0];
|
||||
uchar **stack_bottom = &stack[0];
|
||||
@@ -744,17 +828,17 @@ while (borderPeaks.try_pop(m))
|
||||
// 0 - the pixel might belong to an edge
|
||||
// 1 - the pixel can not belong to an edge
|
||||
// 2 - the pixel does belong to an edge
|
||||
for (int i = 0; i <= src.rows; i++)
|
||||
for (int i = 0; i <= rows; i++)
|
||||
{
|
||||
int* _norm = mag_buf[(i > 0) + 1] + 1;
|
||||
if (i < src.rows)
|
||||
if (i < rows)
|
||||
{
|
||||
short* _dx = dx.ptr<short>(i);
|
||||
short* _dy = dy.ptr<short>(i);
|
||||
|
||||
if (!L2gradient)
|
||||
{
|
||||
int j = 0, width = src.cols * cn;
|
||||
int j = 0, width = cols * cn;
|
||||
#if CV_SSE2
|
||||
if (haveSSE2)
|
||||
{
|
||||
@@ -788,7 +872,7 @@ while (borderPeaks.try_pop(m))
|
||||
}
|
||||
else
|
||||
{
|
||||
int j = 0, width = src.cols * cn;
|
||||
int j = 0, width = cols * cn;
|
||||
#if CV_SSE2
|
||||
if (haveSSE2)
|
||||
{
|
||||
@@ -824,7 +908,7 @@ while (borderPeaks.try_pop(m))
|
||||
|
||||
if (cn > 1)
|
||||
{
|
||||
for(int j = 0, jn = 0; j < src.cols; ++j, jn += cn)
|
||||
for(int j = 0, jn = 0; j < cols; ++j, jn += cn)
|
||||
{
|
||||
int maxIdx = jn;
|
||||
for(int k = 1; k < cn; ++k)
|
||||
@@ -834,7 +918,7 @@ while (borderPeaks.try_pop(m))
|
||||
_dy[j] = _dy[maxIdx];
|
||||
}
|
||||
}
|
||||
_norm[-1] = _norm[src.cols] = 0;
|
||||
_norm[-1] = _norm[cols] = 0;
|
||||
}
|
||||
else
|
||||
memset(_norm-1, 0, /* cn* */mapstep*sizeof(int));
|
||||
@@ -845,7 +929,7 @@ while (borderPeaks.try_pop(m))
|
||||
continue;
|
||||
|
||||
uchar* _map = map + mapstep*i + 1;
|
||||
_map[-1] = _map[src.cols] = 1;
|
||||
_map[-1] = _map[cols] = 1;
|
||||
|
||||
int* _mag = mag_buf[1] + 1; // take the central row
|
||||
ptrdiff_t magstep1 = mag_buf[2] - mag_buf[1];
|
||||
@@ -854,17 +938,17 @@ while (borderPeaks.try_pop(m))
|
||||
const short* _x = dx.ptr<short>(i-1);
|
||||
const short* _y = dy.ptr<short>(i-1);
|
||||
|
||||
if ((stack_top - stack_bottom) + src.cols > maxsize)
|
||||
if ((stack_top - stack_bottom) + cols > maxsize)
|
||||
{
|
||||
int sz = (int)(stack_top - stack_bottom);
|
||||
maxsize = std::max(maxsize * 3/2, sz + src.cols);
|
||||
maxsize = std::max(maxsize * 3/2, sz + cols);
|
||||
stack.resize(maxsize);
|
||||
stack_bottom = &stack[0];
|
||||
stack_top = stack_bottom + sz;
|
||||
}
|
||||
|
||||
int prev_flag = 0;
|
||||
for (int j = 0; j < src.cols; j++)
|
||||
for (int j = 0; j < cols; j++)
|
||||
{
|
||||
#define CANNY_SHIFT 15
|
||||
const int TG22 = (int)(0.4142135623730950488016887242097*(1<<CANNY_SHIFT) + 0.5);
|
||||
@@ -943,18 +1027,18 @@ __ocv_canny_push:
|
||||
if (!m[mapstep+1]) CANNY_PUSH(m + mapstep + 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// the final pass, form the final image
|
||||
const uchar* pmap = map + mapstep + 1;
|
||||
uchar* pdst = dst.ptr();
|
||||
for (int i = 0; i < src.rows; i++, pmap += mapstep, pdst += dst.step)
|
||||
for (int i = 0; i < rows; i++, pmap += mapstep, pdst += dst.step)
|
||||
{
|
||||
for (int j = 0; j < src.cols; j++)
|
||||
for (int j = 0; j < cols; j++)
|
||||
pdst[j] = (uchar)-(pmap[j] >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cv
|
||||
|
||||
void cvCanny( const CvArr* image, CvArr* edges, double threshold1,
|
||||
double threshold2, int aperture_size )
|
||||
{
|
||||
|
||||
@@ -54,7 +54,8 @@ struct greaterThanPtr :
|
||||
public std::binary_function<const float *, const float *, bool>
|
||||
{
|
||||
bool operator () (const float * a, const float * b) const
|
||||
{ return *a > *b; }
|
||||
// Ensure a fully deterministic result of the sort
|
||||
{ return (*a > *b) ? true : (*a < *b) ? false : (a > b); }
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
@@ -66,7 +67,8 @@ struct Corner
|
||||
short x;
|
||||
|
||||
bool operator < (const Corner & c) const
|
||||
{ return val > c.val; }
|
||||
// Ensure a fully deterministic result of the sort
|
||||
{ return (val > c.val) ? true : (val < c.val) ? false : (y > c.y) ? true : (y < c.y) ? false : (x > c.x); }
|
||||
};
|
||||
|
||||
static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners,
|
||||
|
||||
+127
-157
@@ -506,56 +506,52 @@ struct RowVec_8u32s
|
||||
|
||||
if( smallValues )
|
||||
{
|
||||
for( ; i <= width - 16; i += 16 )
|
||||
__m128i z = _mm_setzero_si128();
|
||||
for( ; i <= width - 8; i += 8 )
|
||||
{
|
||||
const uchar* src = _src + i;
|
||||
__m128i f, z = _mm_setzero_si128(), s0 = z, s1 = z, s2 = z, s3 = z;
|
||||
__m128i x0, x1, x2, x3;
|
||||
__m128i s0 = z, s1 = z;
|
||||
|
||||
for( k = 0; k < _ksize; k++, src += cn )
|
||||
{
|
||||
f = _mm_cvtsi32_si128(_kx[k]);
|
||||
__m128i f = _mm_cvtsi32_si128(_kx[k]);
|
||||
f = _mm_shuffle_epi32(f, 0);
|
||||
f = _mm_packs_epi32(f, f);
|
||||
|
||||
x0 = _mm_loadu_si128((const __m128i*)src);
|
||||
x2 = _mm_unpackhi_epi8(x0, z);
|
||||
__m128i x0 = _mm_loadl_epi64((const __m128i*)src);
|
||||
x0 = _mm_unpacklo_epi8(x0, z);
|
||||
x1 = _mm_mulhi_epi16(x0, f);
|
||||
x3 = _mm_mulhi_epi16(x2, f);
|
||||
x0 = _mm_mullo_epi16(x0, f);
|
||||
x2 = _mm_mullo_epi16(x2, f);
|
||||
|
||||
s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(x0, x1));
|
||||
s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(x0, x1));
|
||||
s2 = _mm_add_epi32(s2, _mm_unpacklo_epi16(x2, x3));
|
||||
s3 = _mm_add_epi32(s3, _mm_unpackhi_epi16(x2, x3));
|
||||
__m128i x1 = _mm_unpackhi_epi16(x0, z);
|
||||
x0 = _mm_unpacklo_epi16(x0, z);
|
||||
|
||||
x0 = _mm_madd_epi16(x0, f);
|
||||
x1 = _mm_madd_epi16(x1, f);
|
||||
|
||||
s0 = _mm_add_epi32(s0, x0);
|
||||
s1 = _mm_add_epi32(s1, x1);
|
||||
}
|
||||
|
||||
_mm_store_si128((__m128i*)(dst + i), s0);
|
||||
_mm_store_si128((__m128i*)(dst + i + 4), s1);
|
||||
_mm_store_si128((__m128i*)(dst + i + 8), s2);
|
||||
_mm_store_si128((__m128i*)(dst + i + 12), s3);
|
||||
}
|
||||
|
||||
for( ; i <= width - 4; i += 4 )
|
||||
if( i <= width - 4 )
|
||||
{
|
||||
const uchar* src = _src + i;
|
||||
__m128i f, z = _mm_setzero_si128(), s0 = z, x0, x1;
|
||||
__m128i s0 = z;
|
||||
|
||||
for( k = 0; k < _ksize; k++, src += cn )
|
||||
{
|
||||
f = _mm_cvtsi32_si128(_kx[k]);
|
||||
__m128i f = _mm_cvtsi32_si128(_kx[k]);
|
||||
f = _mm_shuffle_epi32(f, 0);
|
||||
f = _mm_packs_epi32(f, f);
|
||||
|
||||
x0 = _mm_cvtsi32_si128(*(const int*)src);
|
||||
__m128i x0 = _mm_cvtsi32_si128(*(const int*)src);
|
||||
x0 = _mm_unpacklo_epi8(x0, z);
|
||||
x1 = _mm_mulhi_epi16(x0, f);
|
||||
x0 = _mm_mullo_epi16(x0, f);
|
||||
s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(x0, x1));
|
||||
x0 = _mm_unpacklo_epi16(x0, z);
|
||||
x0 = _mm_madd_epi16(x0, f);
|
||||
s0 = _mm_add_epi32(s0, x0);
|
||||
}
|
||||
_mm_store_si128((__m128i*)(dst + i), s0);
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
@@ -652,41 +648,30 @@ struct SymmRowSmallVec_8u32s
|
||||
{
|
||||
__m128i k0 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[0]), 0),
|
||||
k1 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[1]), 0);
|
||||
k0 = _mm_packs_epi32(k0, k0);
|
||||
k1 = _mm_packs_epi32(k1, k1);
|
||||
|
||||
for( ; i <= width - 16; i += 16, src += 16 )
|
||||
for( ; i <= width - 8; i += 8, src += 8 )
|
||||
{
|
||||
__m128i x0, x1, x2, y0, y1, t0, t1, z0, z1, z2, z3;
|
||||
x0 = _mm_loadu_si128((__m128i*)(src - cn));
|
||||
x1 = _mm_loadu_si128((__m128i*)src);
|
||||
x2 = _mm_loadu_si128((__m128i*)(src + cn));
|
||||
y0 = _mm_add_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x2, z));
|
||||
x0 = _mm_add_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x2, z));
|
||||
y1 = _mm_unpackhi_epi8(x1, z);
|
||||
__m128i x0 = _mm_loadl_epi64((__m128i*)(src - cn));
|
||||
__m128i x1 = _mm_loadl_epi64((__m128i*)src);
|
||||
__m128i x2 = _mm_loadl_epi64((__m128i*)(src + cn));
|
||||
|
||||
x0 = _mm_unpacklo_epi8(x0, z);
|
||||
x1 = _mm_unpacklo_epi8(x1, z);
|
||||
x2 = _mm_unpacklo_epi8(x2, z);
|
||||
__m128i x3 = _mm_unpacklo_epi16(x0, x2);
|
||||
__m128i x4 = _mm_unpackhi_epi16(x0, x2);
|
||||
__m128i x5 = _mm_unpacklo_epi16(x1, z);
|
||||
__m128i x6 = _mm_unpackhi_epi16(x1, z);
|
||||
x3 = _mm_madd_epi16(x3, k1);
|
||||
x4 = _mm_madd_epi16(x4, k1);
|
||||
x5 = _mm_madd_epi16(x5, k0);
|
||||
x6 = _mm_madd_epi16(x6, k0);
|
||||
x3 = _mm_add_epi32(x3, x5);
|
||||
x4 = _mm_add_epi32(x4, x6);
|
||||
|
||||
t1 = _mm_mulhi_epi16(x1, k0);
|
||||
t0 = _mm_mullo_epi16(x1, k0);
|
||||
x2 = _mm_mulhi_epi16(x0, k1);
|
||||
x0 = _mm_mullo_epi16(x0, k1);
|
||||
z0 = _mm_unpacklo_epi16(t0, t1);
|
||||
z1 = _mm_unpackhi_epi16(t0, t1);
|
||||
z0 = _mm_add_epi32(z0, _mm_unpacklo_epi16(x0, x2));
|
||||
z1 = _mm_add_epi32(z1, _mm_unpackhi_epi16(x0, x2));
|
||||
|
||||
t1 = _mm_mulhi_epi16(y1, k0);
|
||||
t0 = _mm_mullo_epi16(y1, k0);
|
||||
y1 = _mm_mulhi_epi16(y0, k1);
|
||||
y0 = _mm_mullo_epi16(y0, k1);
|
||||
z2 = _mm_unpacklo_epi16(t0, t1);
|
||||
z3 = _mm_unpackhi_epi16(t0, t1);
|
||||
z2 = _mm_add_epi32(z2, _mm_unpacklo_epi16(y0, y1));
|
||||
z3 = _mm_add_epi32(z3, _mm_unpackhi_epi16(y0, y1));
|
||||
_mm_store_si128((__m128i*)(dst + i), z0);
|
||||
_mm_store_si128((__m128i*)(dst + i + 4), z1);
|
||||
_mm_store_si128((__m128i*)(dst + i + 8), z2);
|
||||
_mm_store_si128((__m128i*)(dst + i + 12), z3);
|
||||
_mm_store_si128((__m128i*)(dst + i), x3);
|
||||
_mm_store_si128((__m128i*)(dst + i + 4), x4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -717,57 +702,45 @@ struct SymmRowSmallVec_8u32s
|
||||
__m128i k0 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[0]), 0),
|
||||
k1 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[1]), 0),
|
||||
k2 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[2]), 0);
|
||||
k0 = _mm_packs_epi32(k0, k0);
|
||||
k1 = _mm_packs_epi32(k1, k1);
|
||||
k2 = _mm_packs_epi32(k2, k2);
|
||||
|
||||
for( ; i <= width - 16; i += 16, src += 16 )
|
||||
for( ; i <= width - 8; i += 8, src += 8 )
|
||||
{
|
||||
__m128i x0, x1, x2, y0, y1, t0, t1, z0, z1, z2, z3;
|
||||
x0 = _mm_loadu_si128((__m128i*)(src - cn));
|
||||
x1 = _mm_loadu_si128((__m128i*)src);
|
||||
x2 = _mm_loadu_si128((__m128i*)(src + cn));
|
||||
y0 = _mm_add_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x2, z));
|
||||
x0 = _mm_add_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x2, z));
|
||||
y1 = _mm_unpackhi_epi8(x1, z);
|
||||
x1 = _mm_unpacklo_epi8(x1, z);
|
||||
__m128i x0 = _mm_loadl_epi64((__m128i*)src);
|
||||
|
||||
t1 = _mm_mulhi_epi16(x1, k0);
|
||||
t0 = _mm_mullo_epi16(x1, k0);
|
||||
x2 = _mm_mulhi_epi16(x0, k1);
|
||||
x0 = _mm_mullo_epi16(x0, k1);
|
||||
z0 = _mm_unpacklo_epi16(t0, t1);
|
||||
z1 = _mm_unpackhi_epi16(t0, t1);
|
||||
z0 = _mm_add_epi32(z0, _mm_unpacklo_epi16(x0, x2));
|
||||
z1 = _mm_add_epi32(z1, _mm_unpackhi_epi16(x0, x2));
|
||||
x0 = _mm_unpacklo_epi8(x0, z);
|
||||
__m128i x1 = _mm_unpacklo_epi16(x0, z);
|
||||
__m128i x2 = _mm_unpackhi_epi16(x0, z);
|
||||
x1 = _mm_madd_epi16(x1, k0);
|
||||
x2 = _mm_madd_epi16(x2, k0);
|
||||
|
||||
t1 = _mm_mulhi_epi16(y1, k0);
|
||||
t0 = _mm_mullo_epi16(y1, k0);
|
||||
y1 = _mm_mulhi_epi16(y0, k1);
|
||||
y0 = _mm_mullo_epi16(y0, k1);
|
||||
z2 = _mm_unpacklo_epi16(t0, t1);
|
||||
z3 = _mm_unpackhi_epi16(t0, t1);
|
||||
z2 = _mm_add_epi32(z2, _mm_unpacklo_epi16(y0, y1));
|
||||
z3 = _mm_add_epi32(z3, _mm_unpackhi_epi16(y0, y1));
|
||||
__m128i x3 = _mm_loadl_epi64((__m128i*)(src - cn));
|
||||
__m128i x4 = _mm_loadl_epi64((__m128i*)(src + cn));
|
||||
|
||||
x0 = _mm_loadu_si128((__m128i*)(src - cn*2));
|
||||
x1 = _mm_loadu_si128((__m128i*)(src + cn*2));
|
||||
y1 = _mm_add_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x1, z));
|
||||
y0 = _mm_add_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x1, z));
|
||||
x3 = _mm_unpacklo_epi8(x3, z);
|
||||
x4 = _mm_unpacklo_epi8(x4, z);
|
||||
__m128i x5 = _mm_unpacklo_epi16(x3, x4);
|
||||
__m128i x6 = _mm_unpackhi_epi16(x3, x4);
|
||||
x5 = _mm_madd_epi16(x5, k1);
|
||||
x6 = _mm_madd_epi16(x6, k1);
|
||||
x1 = _mm_add_epi32(x1, x5);
|
||||
x2 = _mm_add_epi32(x2, x6);
|
||||
|
||||
t1 = _mm_mulhi_epi16(y0, k2);
|
||||
t0 = _mm_mullo_epi16(y0, k2);
|
||||
y0 = _mm_mullo_epi16(y1, k2);
|
||||
y1 = _mm_mulhi_epi16(y1, k2);
|
||||
z0 = _mm_add_epi32(z0, _mm_unpacklo_epi16(t0, t1));
|
||||
z1 = _mm_add_epi32(z1, _mm_unpackhi_epi16(t0, t1));
|
||||
z2 = _mm_add_epi32(z2, _mm_unpacklo_epi16(y0, y1));
|
||||
z3 = _mm_add_epi32(z3, _mm_unpackhi_epi16(y0, y1));
|
||||
x3 = _mm_loadl_epi64((__m128i*)(src - cn*2));
|
||||
x4 = _mm_loadl_epi64((__m128i*)(src + cn*2));
|
||||
|
||||
_mm_store_si128((__m128i*)(dst + i), z0);
|
||||
_mm_store_si128((__m128i*)(dst + i + 4), z1);
|
||||
_mm_store_si128((__m128i*)(dst + i + 8), z2);
|
||||
_mm_store_si128((__m128i*)(dst + i + 12), z3);
|
||||
x3 = _mm_unpacklo_epi8(x3, z);
|
||||
x4 = _mm_unpacklo_epi8(x4, z);
|
||||
x5 = _mm_unpacklo_epi16(x3, x4);
|
||||
x6 = _mm_unpackhi_epi16(x3, x4);
|
||||
x5 = _mm_madd_epi16(x5, k2);
|
||||
x6 = _mm_madd_epi16(x6, k2);
|
||||
x1 = _mm_add_epi32(x1, x5);
|
||||
x2 = _mm_add_epi32(x2, x6);
|
||||
|
||||
_mm_store_si128((__m128i*)(dst + i), x1);
|
||||
_mm_store_si128((__m128i*)(dst + i + 4), x2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -791,77 +764,75 @@ struct SymmRowSmallVec_8u32s
|
||||
}
|
||||
else
|
||||
{
|
||||
__m128i k1 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[1]), 0);
|
||||
k1 = _mm_packs_epi32(k1, k1);
|
||||
__m128i k0 = _mm_set_epi32(-kx[1], kx[1], -kx[1], kx[1]);
|
||||
k0 = _mm_packs_epi32(k0, k0);
|
||||
|
||||
for( ; i <= width - 16; i += 16, src += 16 )
|
||||
{
|
||||
__m128i x0, x1, y0, y1, z0, z1, z2, z3;
|
||||
x0 = _mm_loadu_si128((__m128i*)(src + cn));
|
||||
x1 = _mm_loadu_si128((__m128i*)(src - cn));
|
||||
y0 = _mm_sub_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x1, z));
|
||||
x0 = _mm_sub_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x1, z));
|
||||
__m128i x0 = _mm_loadu_si128((__m128i*)(src + cn));
|
||||
__m128i x1 = _mm_loadu_si128((__m128i*)(src - cn));
|
||||
|
||||
x1 = _mm_mulhi_epi16(x0, k1);
|
||||
x0 = _mm_mullo_epi16(x0, k1);
|
||||
z0 = _mm_unpacklo_epi16(x0, x1);
|
||||
z1 = _mm_unpackhi_epi16(x0, x1);
|
||||
__m128i x2 = _mm_unpacklo_epi8(x0, z);
|
||||
__m128i x3 = _mm_unpacklo_epi8(x1, z);
|
||||
__m128i x4 = _mm_unpackhi_epi8(x0, z);
|
||||
__m128i x5 = _mm_unpackhi_epi8(x1, z);
|
||||
__m128i x6 = _mm_unpacklo_epi16(x2, x3);
|
||||
__m128i x7 = _mm_unpacklo_epi16(x4, x5);
|
||||
__m128i x8 = _mm_unpackhi_epi16(x2, x3);
|
||||
__m128i x9 = _mm_unpackhi_epi16(x4, x5);
|
||||
x6 = _mm_madd_epi16(x6, k0);
|
||||
x7 = _mm_madd_epi16(x7, k0);
|
||||
x8 = _mm_madd_epi16(x8, k0);
|
||||
x9 = _mm_madd_epi16(x9, k0);
|
||||
|
||||
y1 = _mm_mulhi_epi16(y0, k1);
|
||||
y0 = _mm_mullo_epi16(y0, k1);
|
||||
z2 = _mm_unpacklo_epi16(y0, y1);
|
||||
z3 = _mm_unpackhi_epi16(y0, y1);
|
||||
_mm_store_si128((__m128i*)(dst + i), z0);
|
||||
_mm_store_si128((__m128i*)(dst + i + 4), z1);
|
||||
_mm_store_si128((__m128i*)(dst + i + 8), z2);
|
||||
_mm_store_si128((__m128i*)(dst + i + 12), z3);
|
||||
_mm_store_si128((__m128i*)(dst + i), x6);
|
||||
_mm_store_si128((__m128i*)(dst + i + 4), x8);
|
||||
_mm_store_si128((__m128i*)(dst + i + 8), x7);
|
||||
_mm_store_si128((__m128i*)(dst + i + 12), x9);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( _ksize == 5 )
|
||||
{
|
||||
__m128i k0 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[0]), 0),
|
||||
k1 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[1]), 0),
|
||||
k2 = _mm_shuffle_epi32(_mm_cvtsi32_si128(kx[2]), 0);
|
||||
__m128i k0 = _mm_loadl_epi64((__m128i*)(kx + 1));
|
||||
k0 = _mm_unpacklo_epi64(k0, k0);
|
||||
k0 = _mm_packs_epi32(k0, k0);
|
||||
k1 = _mm_packs_epi32(k1, k1);
|
||||
k2 = _mm_packs_epi32(k2, k2);
|
||||
|
||||
for( ; i <= width - 16; i += 16, src += 16 )
|
||||
{
|
||||
__m128i x0, x1, x2, y0, y1, t0, t1, z0, z1, z2, z3;
|
||||
x0 = _mm_loadu_si128((__m128i*)(src + cn));
|
||||
x2 = _mm_loadu_si128((__m128i*)(src - cn));
|
||||
y0 = _mm_sub_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x2, z));
|
||||
x0 = _mm_sub_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x2, z));
|
||||
__m128i x0 = _mm_loadu_si128((__m128i*)(src + cn));
|
||||
__m128i x1 = _mm_loadu_si128((__m128i*)(src - cn));
|
||||
|
||||
x2 = _mm_mulhi_epi16(x0, k1);
|
||||
x0 = _mm_mullo_epi16(x0, k1);
|
||||
z0 = _mm_unpacklo_epi16(x0, x2);
|
||||
z1 = _mm_unpackhi_epi16(x0, x2);
|
||||
y1 = _mm_mulhi_epi16(y0, k1);
|
||||
y0 = _mm_mullo_epi16(y0, k1);
|
||||
z2 = _mm_unpacklo_epi16(y0, y1);
|
||||
z3 = _mm_unpackhi_epi16(y0, y1);
|
||||
__m128i x2 = _mm_unpackhi_epi8(x0, z);
|
||||
__m128i x3 = _mm_unpackhi_epi8(x1, z);
|
||||
x0 = _mm_unpacklo_epi8(x0, z);
|
||||
x1 = _mm_unpacklo_epi8(x1, z);
|
||||
__m128i x5 = _mm_sub_epi16(x2, x3);
|
||||
__m128i x4 = _mm_sub_epi16(x0, x1);
|
||||
|
||||
x0 = _mm_loadu_si128((__m128i*)(src + cn*2));
|
||||
x1 = _mm_loadu_si128((__m128i*)(src - cn*2));
|
||||
y1 = _mm_sub_epi16(_mm_unpackhi_epi8(x0, z), _mm_unpackhi_epi8(x1, z));
|
||||
y0 = _mm_sub_epi16(_mm_unpacklo_epi8(x0, z), _mm_unpacklo_epi8(x1, z));
|
||||
__m128i x6 = _mm_loadu_si128((__m128i*)(src + cn * 2));
|
||||
__m128i x7 = _mm_loadu_si128((__m128i*)(src - cn * 2));
|
||||
|
||||
t1 = _mm_mulhi_epi16(y0, k2);
|
||||
t0 = _mm_mullo_epi16(y0, k2);
|
||||
y0 = _mm_mullo_epi16(y1, k2);
|
||||
y1 = _mm_mulhi_epi16(y1, k2);
|
||||
z0 = _mm_add_epi32(z0, _mm_unpacklo_epi16(t0, t1));
|
||||
z1 = _mm_add_epi32(z1, _mm_unpackhi_epi16(t0, t1));
|
||||
z2 = _mm_add_epi32(z2, _mm_unpacklo_epi16(y0, y1));
|
||||
z3 = _mm_add_epi32(z3, _mm_unpackhi_epi16(y0, y1));
|
||||
__m128i x8 = _mm_unpackhi_epi8(x6, z);
|
||||
__m128i x9 = _mm_unpackhi_epi8(x7, z);
|
||||
x6 = _mm_unpacklo_epi8(x6, z);
|
||||
x7 = _mm_unpacklo_epi8(x7, z);
|
||||
__m128i x11 = _mm_sub_epi16(x8, x9);
|
||||
__m128i x10 = _mm_sub_epi16(x6, x7);
|
||||
|
||||
_mm_store_si128((__m128i*)(dst + i), z0);
|
||||
_mm_store_si128((__m128i*)(dst + i + 4), z1);
|
||||
_mm_store_si128((__m128i*)(dst + i + 8), z2);
|
||||
_mm_store_si128((__m128i*)(dst + i + 12), z3);
|
||||
__m128i x13 = _mm_unpackhi_epi16(x5, x11);
|
||||
__m128i x12 = _mm_unpackhi_epi16(x4, x10);
|
||||
x5 = _mm_unpacklo_epi16(x5, x11);
|
||||
x4 = _mm_unpacklo_epi16(x4, x10);
|
||||
x5 = _mm_madd_epi16(x5, k0);
|
||||
x4 = _mm_madd_epi16(x4, k0);
|
||||
x13 = _mm_madd_epi16(x13, k0);
|
||||
x12 = _mm_madd_epi16(x12, k0);
|
||||
|
||||
_mm_store_si128((__m128i*)(dst + i), x4);
|
||||
_mm_store_si128((__m128i*)(dst + i + 4), x12);
|
||||
_mm_store_si128((__m128i*)(dst + i + 8), x5);
|
||||
_mm_store_si128((__m128i*)(dst + i + 12), x13);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -870,19 +841,18 @@ struct SymmRowSmallVec_8u32s
|
||||
kx -= _ksize/2;
|
||||
for( ; i <= width - 4; i += 4, src += 4 )
|
||||
{
|
||||
__m128i f, s0 = z, x0, x1;
|
||||
__m128i s0 = z;
|
||||
|
||||
for( k = j = 0; k < _ksize; k++, j += cn )
|
||||
{
|
||||
f = _mm_cvtsi32_si128(kx[k]);
|
||||
__m128i f = _mm_cvtsi32_si128(kx[k]);
|
||||
f = _mm_shuffle_epi32(f, 0);
|
||||
f = _mm_packs_epi32(f, f);
|
||||
|
||||
x0 = _mm_cvtsi32_si128(*(const int*)(src + j));
|
||||
__m128i x0 = _mm_cvtsi32_si128(*(const int*)(src + j));
|
||||
x0 = _mm_unpacklo_epi8(x0, z);
|
||||
x1 = _mm_mulhi_epi16(x0, f);
|
||||
x0 = _mm_mullo_epi16(x0, f);
|
||||
s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(x0, x1));
|
||||
x0 = _mm_unpacklo_epi16(x0, z);
|
||||
x0 = _mm_madd_epi16(x0, f);
|
||||
s0 = _mm_add_epi32(s0, x0);
|
||||
}
|
||||
_mm_store_si128((__m128i*)(dst + i), s0);
|
||||
}
|
||||
|
||||
@@ -4617,14 +4617,14 @@ static bool ocl_linearPolar(InputArray _src, OutputArray _dst,
|
||||
size_t w = dsize.width;
|
||||
size_t h = dsize.height;
|
||||
String buildOptions;
|
||||
unsigned mem_szie = 32;
|
||||
unsigned mem_size = 32;
|
||||
if (flags & CV_WARP_INVERSE_MAP)
|
||||
{
|
||||
buildOptions = "-D InverseMap";
|
||||
}
|
||||
else
|
||||
{
|
||||
buildOptions = format("-D ForwardMap -D MEM_SIZE=%d", mem_szie);
|
||||
buildOptions = format("-D ForwardMap -D MEM_SIZE=%d", mem_size);
|
||||
}
|
||||
String retval;
|
||||
ocl::Program p(ocl::imgproc::linearPolar_oclsrc, buildOptions, retval);
|
||||
@@ -4662,7 +4662,7 @@ static bool ocl_linearPolar(InputArray _src, OutputArray _dst,
|
||||
|
||||
}
|
||||
size_t globalThreads[2] = { (size_t)dsize.width , (size_t)dsize.height };
|
||||
size_t localThreads[2] = { mem_szie , mem_szie };
|
||||
size_t localThreads[2] = { mem_size , mem_size };
|
||||
k.run(2, globalThreads, localThreads, false);
|
||||
remap(src, _dst, mapx, mapy, flags & cv::INTER_MAX, (flags & CV_WARP_FILL_OUTLIERS) ? cv::BORDER_CONSTANT : cv::BORDER_TRANSPARENT);
|
||||
return true;
|
||||
@@ -4686,14 +4686,14 @@ static bool ocl_logPolar(InputArray _src, OutputArray _dst,
|
||||
size_t w = dsize.width;
|
||||
size_t h = dsize.height;
|
||||
String buildOptions;
|
||||
unsigned mem_szie = 32;
|
||||
unsigned mem_size = 32;
|
||||
if (flags & CV_WARP_INVERSE_MAP)
|
||||
{
|
||||
buildOptions = "-D InverseMap";
|
||||
}
|
||||
else
|
||||
{
|
||||
buildOptions = format("-D ForwardMap -D MEM_SIZE=%d", mem_szie);
|
||||
buildOptions = format("-D ForwardMap -D MEM_SIZE=%d", mem_size);
|
||||
}
|
||||
String retval;
|
||||
ocl::Program p(ocl::imgproc::logPolar_oclsrc, buildOptions, retval);
|
||||
@@ -4731,9 +4731,9 @@ static bool ocl_logPolar(InputArray _src, OutputArray _dst,
|
||||
k.args(ocl_mapx, ocl_mapy, ascale, (float)M, center.x, center.y, ANGLE_BORDER, (unsigned)dsize.width, (unsigned)dsize.height);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
size_t globalThreads[2] = { (size_t)dsize.width , (size_t)dsize.height };
|
||||
size_t localThreads[2] = { mem_szie , mem_szie };
|
||||
size_t localThreads[2] = { mem_size , mem_size };
|
||||
k.run(2, globalThreads, localThreads, false);
|
||||
remap(src, _dst, mapx, mapy, flags & cv::INTER_MAX, (flags & CV_WARP_FILL_OUTLIERS) ? cv::BORDER_CONSTANT : cv::BORDER_TRANSPARENT);
|
||||
return true;
|
||||
|
||||
@@ -345,37 +345,42 @@ struct MomentsInTile_SIMD<ushort, int, int64>
|
||||
|
||||
if (useSIMD)
|
||||
{
|
||||
__m128i vx_init0 = _mm_setr_epi32(0, 1, 2, 3), vx_init1 = _mm_setr_epi32(4, 5, 6, 7),
|
||||
v_delta = _mm_set1_epi32(8), v_zero = _mm_setzero_si128(), v_x0 = v_zero,
|
||||
v_x1 = v_zero, v_x2 = v_zero, v_x3 = v_zero, v_ix0 = vx_init0, v_ix1 = vx_init1;
|
||||
__m128i v_delta = _mm_set1_epi32(4), v_zero = _mm_setzero_si128(), v_x0 = v_zero,
|
||||
v_x1 = v_zero, v_x2 = v_zero, v_x3 = v_zero, v_ix0 = _mm_setr_epi32(0, 1, 2, 3);
|
||||
|
||||
for( ; x <= len - 8; x += 8 )
|
||||
for( ; x <= len - 4; x += 4 )
|
||||
{
|
||||
__m128i v_src = _mm_loadu_si128((const __m128i *)(ptr + x));
|
||||
__m128i v_src0 = _mm_unpacklo_epi16(v_src, v_zero), v_src1 = _mm_unpackhi_epi16(v_src, v_zero);
|
||||
__m128i v_src = _mm_loadl_epi64((const __m128i *)(ptr + x));
|
||||
v_src = _mm_unpacklo_epi16(v_src, v_zero);
|
||||
|
||||
v_x0 = _mm_add_epi32(v_x0, _mm_add_epi32(v_src0, v_src1));
|
||||
__m128i v_x1_0 = _mm_mullo_epi32(v_src0, v_ix0), v_x1_1 = _mm_mullo_epi32(v_src1, v_ix1);
|
||||
v_x1 = _mm_add_epi32(v_x1, _mm_add_epi32(v_x1_0, v_x1_1));
|
||||
v_x0 = _mm_add_epi32(v_x0, v_src);
|
||||
v_x1 = _mm_add_epi32(v_x1, _mm_mullo_epi32(v_src, v_ix0));
|
||||
|
||||
__m128i v_2ix0 = _mm_mullo_epi32(v_ix0, v_ix0), v_2ix1 = _mm_mullo_epi32(v_ix1, v_ix1);
|
||||
v_x2 = _mm_add_epi32(v_x2, _mm_add_epi32(_mm_mullo_epi32(v_2ix0, v_src0), _mm_mullo_epi32(v_2ix1, v_src1)));
|
||||
__m128i v_ix1 = _mm_mullo_epi32(v_ix0, v_ix0);
|
||||
v_x2 = _mm_add_epi32(v_x2, _mm_mullo_epi32(v_src, v_ix1));
|
||||
|
||||
__m128i t = _mm_add_epi32(_mm_mullo_epi32(v_2ix0, v_x1_0), _mm_mullo_epi32(v_2ix1, v_x1_1));
|
||||
v_x3 = _mm_add_epi64(v_x3, _mm_add_epi64(_mm_unpacklo_epi32(t, v_zero), _mm_unpackhi_epi32(t, v_zero)));
|
||||
v_ix1 = _mm_mullo_epi32(v_ix0, v_ix1);
|
||||
v_src = _mm_mullo_epi32(v_src, v_ix1);
|
||||
v_x3 = _mm_add_epi64(v_x3, _mm_add_epi64(_mm_unpacklo_epi32(v_src, v_zero), _mm_unpackhi_epi32(v_src, v_zero)));
|
||||
|
||||
v_ix0 = _mm_add_epi32(v_ix0, v_delta);
|
||||
v_ix1 = _mm_add_epi32(v_ix1, v_delta);
|
||||
}
|
||||
|
||||
_mm_store_si128((__m128i*)buf, v_x0);
|
||||
x0 = buf[0] + buf[1] + buf[2] + buf[3];
|
||||
_mm_store_si128((__m128i*)buf, v_x1);
|
||||
x1 = buf[0] + buf[1] + buf[2] + buf[3];
|
||||
_mm_store_si128((__m128i*)buf, v_x2);
|
||||
x2 = buf[0] + buf[1] + buf[2] + buf[3];
|
||||
|
||||
__m128i v_x01_lo = _mm_unpacklo_epi32(v_x0, v_x1);
|
||||
__m128i v_x22_lo = _mm_unpacklo_epi32(v_x2, v_x2);
|
||||
__m128i v_x01_hi = _mm_unpackhi_epi32(v_x0, v_x1);
|
||||
__m128i v_x22_hi = _mm_unpackhi_epi32(v_x2, v_x2);
|
||||
v_x01_lo = _mm_add_epi32(v_x01_lo, v_x01_hi);
|
||||
v_x22_lo = _mm_add_epi32(v_x22_lo, v_x22_hi);
|
||||
__m128i v_x0122_lo = _mm_unpacklo_epi64(v_x01_lo, v_x22_lo);
|
||||
__m128i v_x0122_hi = _mm_unpackhi_epi64(v_x01_lo, v_x22_lo);
|
||||
v_x0122_lo = _mm_add_epi32(v_x0122_lo, v_x0122_hi);
|
||||
_mm_store_si128((__m128i*)buf64, v_x3);
|
||||
_mm_store_si128((__m128i*)buf, v_x0122_lo);
|
||||
|
||||
x0 = buf[0];
|
||||
x1 = buf[1];
|
||||
x2 = buf[2];
|
||||
x3 = buf64[0] + buf64[1];
|
||||
}
|
||||
|
||||
|
||||
+123
-12
@@ -3017,16 +3017,16 @@ public:
|
||||
_g = _mm_mul_ps(_g, _w);
|
||||
_r = _mm_mul_ps(_r, _w);
|
||||
|
||||
_w = _mm_hadd_ps(_w, _b);
|
||||
_g = _mm_hadd_ps(_g, _r);
|
||||
_w = _mm_hadd_ps(_w, _b);
|
||||
_g = _mm_hadd_ps(_g, _r);
|
||||
|
||||
_w = _mm_hadd_ps(_w, _g);
|
||||
_mm_store_ps(bufSum, _w);
|
||||
_w = _mm_hadd_ps(_w, _g);
|
||||
_mm_store_ps(bufSum, _w);
|
||||
|
||||
wsum += bufSum[0];
|
||||
sum_b += bufSum[1];
|
||||
sum_g += bufSum[2];
|
||||
sum_r += bufSum[3];
|
||||
wsum += bufSum[0];
|
||||
sum_b += bufSum[1];
|
||||
sum_g += bufSum[2];
|
||||
sum_r += bufSum[3];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -3293,11 +3293,15 @@ public:
|
||||
{
|
||||
int i, j, k;
|
||||
Size size = dest->size();
|
||||
#if CV_SSE3
|
||||
#if CV_SSE3 || CV_NEON
|
||||
int CV_DECL_ALIGNED(16) idxBuf[4];
|
||||
float CV_DECL_ALIGNED(16) bufSum32[4];
|
||||
static const unsigned int CV_DECL_ALIGNED(16) bufSignMask[] = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
|
||||
#endif
|
||||
#if CV_SSE3
|
||||
bool haveSSE3 = checkHardwareSupport(CV_CPU_SSE3);
|
||||
#elif CV_NEON
|
||||
bool haveNEON = checkHardwareSupport(CV_CPU_NEON);
|
||||
#endif
|
||||
|
||||
for( i = range.start; i < range.end; i++ )
|
||||
@@ -3339,15 +3343,56 @@ public:
|
||||
__m128 _w = _mm_mul_ps(_sw, _mm_add_ps(_explut, _mm_mul_ps(_alpha, _mm_sub_ps(_explut1, _explut))));
|
||||
_val = _mm_mul_ps(_w, _val);
|
||||
|
||||
_sw = _mm_hadd_ps(_w, _val);
|
||||
_sw = _mm_hadd_ps(_sw, _sw);
|
||||
psum = _mm_add_ps(_sw, psum);
|
||||
_sw = _mm_hadd_ps(_w, _val);
|
||||
_sw = _mm_hadd_ps(_sw, _sw);
|
||||
psum = _mm_add_ps(_sw, psum);
|
||||
}
|
||||
_mm_storel_pi((__m64*)bufSum32, psum);
|
||||
|
||||
sum = bufSum32[1];
|
||||
wsum = bufSum32[0];
|
||||
}
|
||||
#elif CV_NEON
|
||||
if( haveNEON )
|
||||
{
|
||||
float32x2_t psum = vdup_n_f32(0.0f);
|
||||
const volatile float32x4_t _val0 = vdupq_n_f32(sptr[j]);
|
||||
const float32x4_t _scale_index = vdupq_n_f32(scale_index);
|
||||
const uint32x4_t _signMask = vld1q_u32(bufSignMask);
|
||||
|
||||
for( ; k <= maxk - 4 ; k += 4 )
|
||||
{
|
||||
float32x4_t _sw = vld1q_f32(space_weight + k);
|
||||
float CV_DECL_ALIGNED(16) _data[] = {sptr[j + space_ofs[k]], sptr[j + space_ofs[k+1]],
|
||||
sptr[j + space_ofs[k+2]], sptr[j + space_ofs[k+3]],};
|
||||
float32x4_t _val = vld1q_f32(_data);
|
||||
float32x4_t _alpha = vsubq_f32(_val, _val0);
|
||||
_alpha = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(_alpha), _signMask));
|
||||
_alpha = vmulq_f32(_alpha, _scale_index);
|
||||
int32x4_t _idx = vcvtq_s32_f32(_alpha);
|
||||
vst1q_s32(idxBuf, _idx);
|
||||
_alpha = vsubq_f32(_alpha, vcvtq_f32_s32(_idx));
|
||||
|
||||
bufSum32[0] = expLUT[idxBuf[0]];
|
||||
bufSum32[1] = expLUT[idxBuf[1]];
|
||||
bufSum32[2] = expLUT[idxBuf[2]];
|
||||
bufSum32[3] = expLUT[idxBuf[3]];
|
||||
float32x4_t _explut = vld1q_f32(bufSum32);
|
||||
bufSum32[0] = expLUT[idxBuf[0]+1];
|
||||
bufSum32[1] = expLUT[idxBuf[1]+1];
|
||||
bufSum32[2] = expLUT[idxBuf[2]+1];
|
||||
bufSum32[3] = expLUT[idxBuf[3]+1];
|
||||
float32x4_t _explut1 = vld1q_f32(bufSum32);
|
||||
|
||||
float32x4_t _w = vmulq_f32(_sw, vaddq_f32(_explut, vmulq_f32(_alpha, vsubq_f32(_explut1, _explut))));
|
||||
_val = vmulq_f32(_w, _val);
|
||||
|
||||
float32x2_t _wval = vpadd_f32(vpadd_f32(vget_low_f32(_w),vget_high_f32(_w)), vpadd_f32(vget_low_f32(_val), vget_high_f32(_val)));
|
||||
psum = vadd_f32(_wval, psum);
|
||||
}
|
||||
sum = vget_lane_f32(psum, 1);
|
||||
wsum = vget_lane_f32(psum, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
for( ; k < maxk; k++ )
|
||||
@@ -3427,6 +3472,72 @@ public:
|
||||
sum_g = bufSum32[2];
|
||||
sum_r = bufSum32[3];
|
||||
}
|
||||
#elif CV_NEON
|
||||
if( haveNEON )
|
||||
{
|
||||
float32x4_t sum = vdupq_n_f32(0.0f);
|
||||
const float32x4_t _b0 = vdupq_n_f32(b0);
|
||||
const float32x4_t _g0 = vdupq_n_f32(g0);
|
||||
const float32x4_t _r0 = vdupq_n_f32(r0);
|
||||
const float32x4_t _scale_index = vdupq_n_f32(scale_index);
|
||||
const uint32x4_t _signMask = vld1q_u32(bufSignMask);
|
||||
|
||||
for( ; k <= maxk-4; k += 4 )
|
||||
{
|
||||
float32x4_t _sw = vld1q_f32(space_weight + k);
|
||||
|
||||
const float* const sptr_k0 = sptr + j + space_ofs[k];
|
||||
const float* const sptr_k1 = sptr + j + space_ofs[k+1];
|
||||
const float* const sptr_k2 = sptr + j + space_ofs[k+2];
|
||||
const float* const sptr_k3 = sptr + j + space_ofs[k+3];
|
||||
|
||||
float32x4_t _v0 = vld1q_f32(sptr_k0);
|
||||
float32x4_t _v1 = vld1q_f32(sptr_k1);
|
||||
float32x4_t _v2 = vld1q_f32(sptr_k2);
|
||||
float32x4_t _v3 = vld1q_f32(sptr_k3);
|
||||
|
||||
float32x4x2_t v01 = vtrnq_f32(_v0, _v1);
|
||||
float32x4x2_t v23 = vtrnq_f32(_v2, _v3);
|
||||
float32x4_t _b = vcombine_f32(vget_low_f32(v01.val[0]), vget_low_f32(v23.val[0]));
|
||||
float32x4_t _g = vcombine_f32(vget_low_f32(v01.val[1]), vget_low_f32(v23.val[1]));
|
||||
float32x4_t _r = vcombine_f32(vget_high_f32(v01.val[0]), vget_high_f32(v23.val[0]));
|
||||
|
||||
float32x4_t _bt = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(vsubq_f32(_b, _b0)), _signMask));
|
||||
float32x4_t _gt = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(vsubq_f32(_g, _g0)), _signMask));
|
||||
float32x4_t _rt = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(vsubq_f32(_r, _r0)), _signMask));
|
||||
float32x4_t _alpha = vmulq_f32(_scale_index, vaddq_f32(_bt, vaddq_f32(_gt, _rt)));
|
||||
|
||||
int32x4_t _idx = vcvtq_s32_f32(_alpha);
|
||||
vst1q_s32((int*)idxBuf, _idx);
|
||||
bufSum32[0] = expLUT[idxBuf[0]];
|
||||
bufSum32[1] = expLUT[idxBuf[1]];
|
||||
bufSum32[2] = expLUT[idxBuf[2]];
|
||||
bufSum32[3] = expLUT[idxBuf[3]];
|
||||
float32x4_t _explut = vld1q_f32(bufSum32);
|
||||
bufSum32[0] = expLUT[idxBuf[0]+1];
|
||||
bufSum32[1] = expLUT[idxBuf[1]+1];
|
||||
bufSum32[2] = expLUT[idxBuf[2]+1];
|
||||
bufSum32[3] = expLUT[idxBuf[3]+1];
|
||||
float32x4_t _explut1 = vld1q_f32(bufSum32);
|
||||
|
||||
float32x4_t _w = vmulq_f32(_sw, vaddq_f32(_explut, vmulq_f32(_alpha, vsubq_f32(_explut1, _explut))));
|
||||
|
||||
_b = vmulq_f32(_b, _w);
|
||||
_g = vmulq_f32(_g, _w);
|
||||
_r = vmulq_f32(_r, _w);
|
||||
|
||||
float32x2_t _wb = vpadd_f32(vpadd_f32(vget_low_f32(_w),vget_high_f32(_w)), vpadd_f32(vget_low_f32(_b), vget_high_f32(_b)));
|
||||
float32x2_t _gr = vpadd_f32(vpadd_f32(vget_low_f32(_g),vget_high_f32(_g)), vpadd_f32(vget_low_f32(_r), vget_high_f32(_r)));
|
||||
|
||||
_w = vcombine_f32(_wb, _gr);
|
||||
sum = vaddq_f32(sum, _w);
|
||||
}
|
||||
vst1q_f32(bufSum32, sum);
|
||||
wsum = bufSum32[0];
|
||||
sum_b = bufSum32[1];
|
||||
sum_g = bufSum32[2];
|
||||
sum_r = bufSum32[3];
|
||||
}
|
||||
#endif
|
||||
|
||||
for(; k < maxk; k++ )
|
||||
|
||||
@@ -43,6 +43,23 @@
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels_imgproc.hpp"
|
||||
|
||||
#if CV_NEON && defined(__aarch64__)
|
||||
#include <arm_neon.h>
|
||||
namespace cv {
|
||||
// Workaround with missing definitions of vreinterpretq_u64_f64/vreinterpretq_f64_u64
|
||||
template <typename T> static inline
|
||||
uint64x2_t vreinterpretq_u64_f64(T a)
|
||||
{
|
||||
return (uint64x2_t) a;
|
||||
}
|
||||
template <typename T> static inline
|
||||
float64x2_t vreinterpretq_f64_u64(T a)
|
||||
{
|
||||
return (float64x2_t) a;
|
||||
}
|
||||
} // namespace cv
|
||||
#endif
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
|
||||
@@ -54,13 +54,13 @@ namespace ocl {
|
||||
////////////////////////////////////////////////////////
|
||||
// Canny
|
||||
|
||||
IMPLEMENT_PARAM_CLASS(AppertureSize, int)
|
||||
IMPLEMENT_PARAM_CLASS(ApertureSize, int)
|
||||
IMPLEMENT_PARAM_CLASS(L2gradient, bool)
|
||||
IMPLEMENT_PARAM_CLASS(UseRoi, bool)
|
||||
|
||||
PARAM_TEST_CASE(Canny, Channels, AppertureSize, L2gradient, UseRoi)
|
||||
PARAM_TEST_CASE(Canny, Channels, ApertureSize, L2gradient, UseRoi)
|
||||
{
|
||||
int cn, apperture_size;
|
||||
int cn, aperture_size;
|
||||
bool useL2gradient, use_roi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src);
|
||||
@@ -69,7 +69,7 @@ PARAM_TEST_CASE(Canny, Channels, AppertureSize, L2gradient, UseRoi)
|
||||
virtual void SetUp()
|
||||
{
|
||||
cn = GET_PARAM(0);
|
||||
apperture_size = GET_PARAM(1);
|
||||
aperture_size = GET_PARAM(1);
|
||||
useL2gradient = GET_PARAM(2);
|
||||
use_roi = GET_PARAM(3);
|
||||
}
|
||||
@@ -105,8 +105,31 @@ OCL_TEST_P(Canny, Accuracy)
|
||||
eps = 12e-3;
|
||||
#endif
|
||||
|
||||
OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, apperture_size, useL2gradient));
|
||||
OCL_ON(cv::Canny(usrc_roi, udst_roi, low_thresh, high_thresh, apperture_size, useL2gradient));
|
||||
OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, aperture_size, useL2gradient));
|
||||
OCL_ON(cv::Canny(usrc_roi, udst_roi, low_thresh, high_thresh, aperture_size, useL2gradient));
|
||||
|
||||
EXPECT_MAT_SIMILAR(dst_roi, udst_roi, eps);
|
||||
EXPECT_MAT_SIMILAR(dst, udst, eps);
|
||||
}
|
||||
|
||||
OCL_TEST_P(Canny, AccuracyCustomGradient)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
const double low_thresh = 50.0, high_thresh = 100.0;
|
||||
double eps = 1e-2;
|
||||
#ifdef ANDROID
|
||||
if (cv::ocl::Device::getDefault().isNVidia())
|
||||
eps = 12e-3;
|
||||
#endif
|
||||
|
||||
OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, aperture_size, useL2gradient));
|
||||
OCL_ON(
|
||||
UMat dx, dy;
|
||||
Sobel(usrc_roi, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
Sobel(usrc_roi, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
cv::Canny(dx, dy, udst_roi, low_thresh, high_thresh, useL2gradient);
|
||||
);
|
||||
|
||||
EXPECT_MAT_SIMILAR(dst_roi, udst_roi, eps);
|
||||
EXPECT_MAT_SIMILAR(dst, udst, eps);
|
||||
@@ -114,7 +137,7 @@ OCL_TEST_P(Canny, Accuracy)
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, Canny, testing::Combine(
|
||||
testing::Values(1, 3),
|
||||
testing::Values(AppertureSize(3), AppertureSize(5)),
|
||||
testing::Values(ApertureSize(3), ApertureSize(5)),
|
||||
testing::Values(L2gradient(false), L2gradient(true)),
|
||||
testing::Values(UseRoi(false), UseRoi(true))));
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ using namespace std;
|
||||
class CV_CannyTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_CannyTest();
|
||||
CV_CannyTest(bool custom_deriv = false);
|
||||
|
||||
protected:
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
@@ -61,10 +61,11 @@ protected:
|
||||
bool use_true_gradient;
|
||||
double threshold1, threshold2;
|
||||
bool test_cpp;
|
||||
bool test_custom_deriv;
|
||||
};
|
||||
|
||||
|
||||
CV_CannyTest::CV_CannyTest()
|
||||
CV_CannyTest::CV_CannyTest(bool custom_deriv)
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
@@ -75,6 +76,7 @@ CV_CannyTest::CV_CannyTest()
|
||||
threshold1 = threshold2 = 0;
|
||||
|
||||
test_cpp = false;
|
||||
test_custom_deriv = custom_deriv;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +101,9 @@ void CV_CannyTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
|
||||
use_true_gradient = cvtest::randInt(rng) % 2 != 0;
|
||||
test_cpp = (cvtest::randInt(rng) & 256) == 0;
|
||||
|
||||
ts->printf(cvtest::TS::LOG, "Canny(size = %d x %d, aperture_size = %d, threshold1 = %g, threshold2 = %g, L2 = %s) test_cpp = %s (test case #%d)\n",
|
||||
sizes[0][0].width, sizes[0][0].height, aperture_size, threshold1, threshold2, use_true_gradient ? "TRUE" : "FALSE", test_cpp ? "TRUE" : "FALSE", test_case_idx);
|
||||
}
|
||||
|
||||
|
||||
@@ -123,9 +128,24 @@ double CV_CannyTest::get_success_error_level( int /*test_case_idx*/, int /*i*/,
|
||||
|
||||
void CV_CannyTest::run_func()
|
||||
{
|
||||
if(!test_cpp)
|
||||
if (test_custom_deriv)
|
||||
{
|
||||
cv::Mat _out = cv::cvarrToMat(test_array[OUTPUT][0]);
|
||||
cv::Mat src = cv::cvarrToMat(test_array[INPUT][0]);
|
||||
cv::Mat dx, dy;
|
||||
int m = aperture_size;
|
||||
Point anchor(m/2, m/2);
|
||||
Mat dxkernel = cvtest::calcSobelKernel2D( 1, 0, m, 0 );
|
||||
Mat dykernel = cvtest::calcSobelKernel2D( 0, 1, m, 0 );
|
||||
cvtest::filter2D(src, dx, CV_16S, dxkernel, anchor, 0, BORDER_REPLICATE);
|
||||
cvtest::filter2D(src, dy, CV_16S, dykernel, anchor, 0, BORDER_REPLICATE);
|
||||
cv::Canny(dx, dy, _out, threshold1, threshold2, use_true_gradient);
|
||||
}
|
||||
else if(!test_cpp)
|
||||
{
|
||||
cvCanny( test_array[INPUT][0], test_array[OUTPUT][0], threshold1, threshold2,
|
||||
aperture_size + (use_true_gradient ? CV_CANNY_L2_GRADIENT : 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat _out = cv::cvarrToMat(test_array[OUTPUT][0]);
|
||||
@@ -283,5 +303,6 @@ int CV_CannyTest::validate_test_results( int test_case_idx )
|
||||
}
|
||||
|
||||
TEST(Imgproc_Canny, accuracy) { CV_CannyTest test; test.safe_run(); }
|
||||
TEST(Imgproc_Canny, accuracy_deriv) { CV_CannyTest test(true); test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// 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) 2016, Itseez, Inc, all rights reserved.
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
// return true if point lies inside ellipse
|
||||
static bool check_pt_in_ellipse(const Point2f& pt, const RotatedRect& el) {
|
||||
Point2f to_pt = pt - el.center;
|
||||
double pt_angle = atan2(to_pt.y, to_pt.x);
|
||||
double el_angle = el.angle * CV_PI / 180;
|
||||
double x_dist = 0.5 * el.size.width * cos(pt_angle + el_angle);
|
||||
double y_dist = 0.5 * el.size.height * sin(pt_angle + el_angle);
|
||||
double el_dist = sqrt(x_dist * x_dist + y_dist * y_dist);
|
||||
return norm(to_pt) < el_dist;
|
||||
}
|
||||
|
||||
// Return true if mass center of fitted points lies inside ellipse
|
||||
static bool fit_and_check_ellipse(const vector<Point2f>& pts) {
|
||||
RotatedRect ellipse = fitEllipse(pts);
|
||||
|
||||
Point2f mass_center;
|
||||
for (size_t i = 0; i < pts.size(); i++) {
|
||||
mass_center += pts[i];
|
||||
}
|
||||
mass_center /= (float)pts.size();
|
||||
|
||||
return check_pt_in_ellipse(mass_center, ellipse);
|
||||
}
|
||||
|
||||
TEST(Imgproc_FitEllipse_Issue_4515, DISABLED_accuracy) {
|
||||
vector<Point2f> pts;
|
||||
pts.push_back(Point2f(327, 317));
|
||||
pts.push_back(Point2f(328, 316));
|
||||
pts.push_back(Point2f(329, 315));
|
||||
pts.push_back(Point2f(330, 314));
|
||||
pts.push_back(Point2f(331, 314));
|
||||
pts.push_back(Point2f(332, 314));
|
||||
pts.push_back(Point2f(333, 315));
|
||||
pts.push_back(Point2f(333, 316));
|
||||
pts.push_back(Point2f(333, 317));
|
||||
pts.push_back(Point2f(333, 318));
|
||||
pts.push_back(Point2f(333, 319));
|
||||
pts.push_back(Point2f(333, 320));
|
||||
|
||||
EXPECT_TRUE(fit_and_check_ellipse(pts));
|
||||
}
|
||||
|
||||
TEST(Imgproc_FitEllipse_Issue_6544, DISABLED_accuracy) {
|
||||
vector<Point2f> pts;
|
||||
pts.push_back(Point2f(924.784f, 764.160f));
|
||||
pts.push_back(Point2f(928.388f, 615.903f));
|
||||
pts.push_back(Point2f(847.4f, 888.014f));
|
||||
pts.push_back(Point2f(929.406f, 741.675f));
|
||||
pts.push_back(Point2f(904.564f, 825.605f));
|
||||
pts.push_back(Point2f(926.742f, 760.746f));
|
||||
pts.push_back(Point2f(863.479f, 873.406f));
|
||||
pts.push_back(Point2f(910.987f, 808.863f));
|
||||
pts.push_back(Point2f(929.145f, 744.976f));
|
||||
pts.push_back(Point2f(917.474f, 791.823f));
|
||||
|
||||
EXPECT_TRUE(fit_and_check_ellipse(pts));
|
||||
}
|
||||
@@ -1442,7 +1442,7 @@ public:
|
||||
//check that while cross-validation there were the samples from all the classes
|
||||
if( class_ranges[class_count] <= 0 )
|
||||
CV_Error( CV_StsBadArg, "While cross-validation one or more of the classes have "
|
||||
"been fell out of the sample. Try to enlarge <Params::k_fold>" );
|
||||
"been fell out of the sample. Try to reduce <Params::k_fold>" );
|
||||
|
||||
if( svmType == NU_SVC )
|
||||
{
|
||||
|
||||
@@ -91,7 +91,7 @@ compensate for the differences in the size of areas. The sums of pixel values ov
|
||||
regions are calculated rapidly using integral images (see below and the integral description).
|
||||
|
||||
To see the object detector at work, have a look at the facedetect demo:
|
||||
<https://github.com/Itseez/opencv/tree/master/samples/cpp/dbt_face_detection.cpp>
|
||||
<https://github.com/opencv/opencv/tree/master/samples/cpp/dbt_face_detection.cpp>
|
||||
|
||||
The following reference is for the detection part only. There is a separate application called
|
||||
opencv_traincascade that can train a cascade of boosted classifiers from a set of samples.
|
||||
|
||||
@@ -222,6 +222,17 @@ void HOGDescriptor::copyTo(HOGDescriptor& c) const
|
||||
c.signedGradient = signedGradient;
|
||||
}
|
||||
|
||||
#if CV_NEON
|
||||
// replace of _mm_set_ps
|
||||
inline float32x4_t vsetq_f32(float f0, float f1, float f2, float f3)
|
||||
{
|
||||
float32x4_t a = vdupq_n_f32(f0);
|
||||
a = vsetq_lane_f32(f1, a, 1);
|
||||
a = vsetq_lane_f32(f2, a, 2);
|
||||
a = vsetq_lane_f32(f3, a, 3);
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle,
|
||||
Size paddingTL, Size paddingBR) const
|
||||
{
|
||||
@@ -259,6 +270,21 @@ void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle,
|
||||
_mm_storeu_ps(_data + i, _mm_cvtepi32_ps(idx));
|
||||
idx = _mm_add_epi32(idx, ifour);
|
||||
}
|
||||
#elif CV_NEON
|
||||
const int indeces[] = { 0, 1, 2, 3 };
|
||||
uint32x4_t idx = *(uint32x4_t*)indeces;
|
||||
uint32x4_t ifour = vdupq_n_u32(4);
|
||||
|
||||
float* const _data = &_lut(0, 0);
|
||||
if( gammaCorrection )
|
||||
for( i = 0; i < 256; i++ )
|
||||
_lut(0,i) = std::sqrt((float)i);
|
||||
else
|
||||
for( i = 0; i < 256; i += 4 )
|
||||
{
|
||||
vst1q_f32(_data + i, vcvtq_f32_u32(idx));
|
||||
idx = vaddq_u32 (idx, ifour);
|
||||
}
|
||||
#else
|
||||
if( gammaCorrection )
|
||||
for( i = 0; i < 256; i++ )
|
||||
@@ -299,6 +325,10 @@ void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle,
|
||||
for ( ; x <= end - 4; x += 4)
|
||||
_mm_storeu_si128((__m128i*)(xmap + x), _mm_mullo_epi16(ithree,
|
||||
_mm_loadu_si128((const __m128i*)(xmap + x))));
|
||||
#elif CV_NEON
|
||||
int32x4_t ithree = vdupq_n_s32(3);
|
||||
for ( ; x <= end - 4; x += 4)
|
||||
vst1q_s32(xmap + x, vmulq_s32(ithree, vld1q_s32(xmap + x)));
|
||||
#endif
|
||||
for ( ; x < end; ++x)
|
||||
xmap[x] *= 3;
|
||||
@@ -368,6 +398,45 @@ void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle,
|
||||
_mm_storeu_ps(dbuf + x, _dx2);
|
||||
_mm_storeu_ps(dbuf + x + width, _dy2);
|
||||
}
|
||||
#elif CV_NEON
|
||||
for( ; x <= width - 4; x += 4 )
|
||||
{
|
||||
int x0 = xmap[x], x1 = xmap[x+1], x2 = xmap[x+2], x3 = xmap[x+3];
|
||||
typedef const uchar* const T;
|
||||
T p02 = imgPtr + xmap[x+1], p00 = imgPtr + xmap[x-1];
|
||||
T p12 = imgPtr + xmap[x+2], p10 = imgPtr + xmap[x];
|
||||
T p22 = imgPtr + xmap[x+3], p20 = p02;
|
||||
T p32 = imgPtr + xmap[x+4], p30 = p12;
|
||||
|
||||
float32x4_t _dx0 = vsubq_f32(vsetq_f32(lut[p02[0]], lut[p12[0]], lut[p22[0]], lut[p32[0]]),
|
||||
vsetq_f32(lut[p00[0]], lut[p10[0]], lut[p20[0]], lut[p30[0]]));
|
||||
float32x4_t _dx1 = vsubq_f32(vsetq_f32(lut[p02[1]], lut[p12[1]], lut[p22[1]], lut[p32[1]]),
|
||||
vsetq_f32(lut[p00[1]], lut[p10[1]], lut[p20[1]], lut[p30[1]]));
|
||||
float32x4_t _dx2 = vsubq_f32(vsetq_f32(lut[p02[2]], lut[p12[2]], lut[p22[2]], lut[p32[2]]),
|
||||
vsetq_f32(lut[p00[2]], lut[p10[2]], lut[p20[2]], lut[p30[2]]));
|
||||
|
||||
float32x4_t _dy0 = vsubq_f32(vsetq_f32(lut[nextPtr[x0]], lut[nextPtr[x1]], lut[nextPtr[x2]], lut[nextPtr[x3]]),
|
||||
vsetq_f32(lut[prevPtr[x0]], lut[prevPtr[x1]], lut[prevPtr[x2]], lut[prevPtr[x3]]));
|
||||
float32x4_t _dy1 = vsubq_f32(vsetq_f32(lut[nextPtr[x0+1]], lut[nextPtr[x1+1]], lut[nextPtr[x2+1]], lut[nextPtr[x3+1]]),
|
||||
vsetq_f32(lut[prevPtr[x0+1]], lut[prevPtr[x1+1]], lut[prevPtr[x2+1]], lut[prevPtr[x3+1]]));
|
||||
float32x4_t _dy2 = vsubq_f32(vsetq_f32(lut[nextPtr[x0+2]], lut[nextPtr[x1+2]], lut[nextPtr[x2+2]], lut[nextPtr[x3+2]]),
|
||||
vsetq_f32(lut[prevPtr[x0+2]], lut[prevPtr[x1+2]], lut[prevPtr[x2+2]], lut[prevPtr[x3+2]]));
|
||||
|
||||
float32x4_t _mag0 = vaddq_f32(vmulq_f32(_dx0, _dx0), vmulq_f32(_dy0, _dy0));
|
||||
float32x4_t _mag1 = vaddq_f32(vmulq_f32(_dx1, _dx1), vmulq_f32(_dy1, _dy1));
|
||||
float32x4_t _mag2 = vaddq_f32(vmulq_f32(_dx2, _dx2), vmulq_f32(_dy2, _dy2));
|
||||
|
||||
uint32x4_t mask = vcgtq_f32(_mag2, _mag1);
|
||||
_dx2 = vbslq_f32(mask, _dx2, _dx1);
|
||||
_dy2 = vbslq_f32(mask, _dy2, _dy1);
|
||||
|
||||
mask = vcgtq_f32(vmaxq_f32(_mag2, _mag1), _mag0);
|
||||
_dx2 = vbslq_f32(mask, _dx2, _dx0);
|
||||
_dy2 = vbslq_f32(mask, _dy2, _dy0);
|
||||
|
||||
vst1q_f32(dbuf + x, _dx2);
|
||||
vst1q_f32(dbuf + x + width, _dy2);
|
||||
}
|
||||
#endif
|
||||
for( ; x < width; x++ )
|
||||
{
|
||||
@@ -600,6 +669,19 @@ void HOGCache::init(const HOGDescriptor* _descriptor,
|
||||
idx = _mm_add_epi32(idx, ifour);
|
||||
_mm_storeu_ps(_di + i, t);
|
||||
}
|
||||
#elif CV_NEON
|
||||
const int a[] = { 0, 1, 2, 3 };
|
||||
int32x4_t idx = vld1q_s32(a);
|
||||
float32x4_t _bw = vdupq_n_f32(bw), _bh = vdupq_n_f32(bh);
|
||||
int32x4_t ifour = vdupq_n_s32(4);
|
||||
|
||||
for (; i <= blockSize.height - 4; i += 4)
|
||||
{
|
||||
float32x4_t t = vsubq_f32(vcvtq_f32_s32(idx), _bh);
|
||||
t = vmulq_f32(t, t);
|
||||
idx = vaddq_s32(idx, ifour);
|
||||
vst1q_f32(_di + i, t);
|
||||
}
|
||||
#endif
|
||||
for ( ; i < blockSize.height; ++i)
|
||||
{
|
||||
@@ -617,6 +699,15 @@ void HOGCache::init(const HOGDescriptor* _descriptor,
|
||||
idx = _mm_add_epi32(idx, ifour);
|
||||
_mm_storeu_ps(_dj + j, t);
|
||||
}
|
||||
#elif CV_NEON
|
||||
idx = vld1q_s32(a);
|
||||
for (; j <= blockSize.width - 4; j += 4)
|
||||
{
|
||||
float32x4_t t = vsubq_f32(vcvtq_f32_s32(idx), _bw);
|
||||
t = vmulq_f32(t, t);
|
||||
idx = vaddq_s32(idx, ifour);
|
||||
vst1q_f32(_dj + j, t);
|
||||
}
|
||||
#endif
|
||||
for ( ; j < blockSize.width; ++j)
|
||||
{
|
||||
@@ -839,6 +930,31 @@ const float* HOGCache::getBlock(Point pt, float* buf)
|
||||
t1 = hist[h1] + hist1[1];
|
||||
hist[h0] = t0; hist[h1] = t1;
|
||||
}
|
||||
#elif CV_NEON
|
||||
float hist0[4], hist1[4];
|
||||
for( ; k < C2; k++ )
|
||||
{
|
||||
const PixData& pk = _pixData[k];
|
||||
const float* const a = gradPtr + pk.gradOfs;
|
||||
const uchar* const h = qanglePtr + pk.qangleOfs;
|
||||
int h0 = h[0], h1 = h[1];
|
||||
|
||||
float32x4_t _a0 = vdupq_n_f32(a[0]), _a1 = vdupq_n_f32(a[1]);
|
||||
float32x4_t _w = vmulq_f32(vdupq_n_f32(pk.gradWeight), vld1q_f32(pk.histWeights));
|
||||
|
||||
float32x4_t _h0 = vsetq_f32((blockHist + pk.histOfs[0])[h0], (blockHist + pk.histOfs[1])[h0], 0, 0);
|
||||
float32x4_t _h1 = vsetq_f32((blockHist + pk.histOfs[0])[h1], (blockHist + pk.histOfs[1])[h1], 0, 0);
|
||||
|
||||
float32x4_t _t0 = vmlaq_f32(_h0, _a0, _w), _t1 = vmlaq_f32(_h1, _a1, _w);
|
||||
vst1q_f32(hist0, _t0);
|
||||
vst1q_f32(hist1, _t1);
|
||||
|
||||
(blockHist + pk.histOfs[0])[h0] = hist0[0];
|
||||
(blockHist + pk.histOfs[1])[h0] = hist0[1];
|
||||
|
||||
(blockHist + pk.histOfs[0])[h1] = hist1[0];
|
||||
(blockHist + pk.histOfs[1])[h1] = hist1[1];
|
||||
}
|
||||
#else
|
||||
for( ; k < C2; k++ )
|
||||
{
|
||||
@@ -918,6 +1034,41 @@ const float* HOGCache::getBlock(Point pt, float* buf)
|
||||
// (pk.histOfs[2] + blockHist)[h1] = hist1[2];
|
||||
// (pk.histOfs[3] + blockHist)[h1] = hist1[3];
|
||||
}
|
||||
#elif CV_NEON
|
||||
for( ; k < C4; k++ )
|
||||
{
|
||||
const PixData& pk = _pixData[k];
|
||||
const float* const a = gradPtr + pk.gradOfs;
|
||||
const uchar* const h = qanglePtr + pk.qangleOfs;
|
||||
int h0 = h[0], h1 = h[1];
|
||||
|
||||
float32x4_t _a0 = vdupq_n_f32(a[0]), _a1 = vdupq_n_f32(a[1]);
|
||||
float32x4_t _w = vmulq_f32(vdupq_n_f32(pk.gradWeight), vld1q_f32(pk.histWeights));
|
||||
|
||||
float32x4_t _h0 = vsetq_f32((blockHist + pk.histOfs[0])[h0],
|
||||
(blockHist + pk.histOfs[1])[h0],
|
||||
(blockHist + pk.histOfs[2])[h0],
|
||||
(blockHist + pk.histOfs[3])[h0]);
|
||||
float32x4_t _h1 = vsetq_f32((blockHist + pk.histOfs[0])[h1],
|
||||
(blockHist + pk.histOfs[1])[h1],
|
||||
(blockHist + pk.histOfs[2])[h1],
|
||||
(blockHist + pk.histOfs[3])[h1]);
|
||||
|
||||
|
||||
float32x4_t _t0 = vmlaq_f32(_h0, _a0, _w), _t1 = vmlaq_f32(_h1, _a1, _w);
|
||||
vst1q_f32(hist0, _t0);
|
||||
vst1q_f32(hist1, _t1);
|
||||
|
||||
(blockHist + pk.histOfs[0])[h0] = hist0[0];
|
||||
(blockHist + pk.histOfs[1])[h0] = hist0[1];
|
||||
(blockHist + pk.histOfs[2])[h0] = hist0[2];
|
||||
(blockHist + pk.histOfs[3])[h0] = hist0[3];
|
||||
|
||||
(blockHist + pk.histOfs[0])[h1] = hist1[0];
|
||||
(blockHist + pk.histOfs[1])[h1] = hist1[1];
|
||||
(blockHist + pk.histOfs[2])[h1] = hist1[2];
|
||||
(blockHist + pk.histOfs[3])[h1] = hist1[3];
|
||||
}
|
||||
#else
|
||||
for( ; k < C4; k++ )
|
||||
{
|
||||
@@ -973,6 +1124,16 @@ void HOGCache::normalizeBlockHistogram(float* _hist) const
|
||||
s = _mm_add_ps(s, _mm_mul_ps(p0, p0));
|
||||
}
|
||||
_mm_storeu_ps(partSum, s);
|
||||
#elif CV_NEON
|
||||
float32x4_t p0 = vld1q_f32(hist);
|
||||
float32x4_t s = vmulq_f32(p0, p0);
|
||||
|
||||
for (i = 4; i <= sz - 4; i += 4)
|
||||
{
|
||||
p0 = vld1q_f32(hist + i);
|
||||
s = vaddq_f32(s, vmulq_f32(p0, p0));
|
||||
}
|
||||
vst1q_f32(partSum, s);
|
||||
#else
|
||||
partSum[0] = 0.0f;
|
||||
partSum[1] = 0.0f;
|
||||
@@ -1014,6 +1175,25 @@ void HOGCache::normalizeBlockHistogram(float* _hist) const
|
||||
}
|
||||
|
||||
_mm_storeu_ps(partSum, s);
|
||||
#elif CV_NEON
|
||||
float32x4_t _scale = vdupq_n_f32(scale);
|
||||
static float32x4_t _threshold = vdupq_n_f32(thresh);
|
||||
|
||||
float32x4_t p = vmulq_f32(_scale, vld1q_f32(hist));
|
||||
p = vminq_f32(p, _threshold);
|
||||
s = vmulq_f32(p, p);
|
||||
vst1q_f32(hist, p);
|
||||
|
||||
for(i = 4 ; i <= sz - 4; i += 4)
|
||||
{
|
||||
p = vld1q_f32(hist + i);
|
||||
p = vmulq_f32(p, _scale);
|
||||
p = vminq_f32(p, _threshold);
|
||||
s = vaddq_f32(s, vmulq_f32(p, p));
|
||||
vst1q_f32(hist + i, p);
|
||||
}
|
||||
|
||||
vst1q_f32(partSum, s);
|
||||
#else
|
||||
partSum[0] = 0.0f;
|
||||
partSum[1] = 0.0f;
|
||||
@@ -1048,6 +1228,13 @@ void HOGCache::normalizeBlockHistogram(float* _hist) const
|
||||
__m128 t = _mm_mul_ps(_scale2, _mm_loadu_ps(hist + i));
|
||||
_mm_storeu_ps(hist + i, t);
|
||||
}
|
||||
#elif CV_NEON
|
||||
float32x4_t _scale2 = vdupq_n_f32(scale);
|
||||
for ( ; i <= sz - 4; i += 4)
|
||||
{
|
||||
float32x4_t t = vmulq_f32(_scale2, vld1q_f32(hist + i));
|
||||
vst1q_f32(hist + i, t);
|
||||
}
|
||||
#endif
|
||||
for ( ; i < sz; ++i)
|
||||
hist[i] *= scale;
|
||||
@@ -1489,7 +1676,7 @@ void HOGDescriptor::detect(const Mat& img,
|
||||
double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0;
|
||||
std::vector<float> blockHist(blockHistogramSize);
|
||||
|
||||
#if CV_SSE2
|
||||
#if CV_SSE2 || CV_NEON
|
||||
float partSum[4];
|
||||
#endif
|
||||
|
||||
@@ -1535,6 +1722,23 @@ void HOGDescriptor::detect(const Mat& img,
|
||||
double t0 = partSum[0] + partSum[1];
|
||||
double t1 = partSum[2] + partSum[3];
|
||||
s += t0 + t1;
|
||||
#elif CV_NEON
|
||||
float32x4_t _vec = vld1q_f32(vec);
|
||||
float32x4_t _svmVec = vld1q_f32(svmVec);
|
||||
float32x4_t sum = vmulq_f32(_svmVec, _vec);
|
||||
|
||||
for( k = 4; k <= blockHistogramSize - 4; k += 4 )
|
||||
{
|
||||
_vec = vld1q_f32(vec + k);
|
||||
_svmVec = vld1q_f32(svmVec + k);
|
||||
|
||||
sum = vaddq_f32(sum, vmulq_f32(_vec, _svmVec));
|
||||
}
|
||||
|
||||
vst1q_f32(partSum, sum);
|
||||
double t0 = partSum[0] + partSum[1];
|
||||
double t1 = partSum[2] + partSum[3];
|
||||
s += t0 + t1;
|
||||
#else
|
||||
for( k = 0; k <= blockHistogramSize - 4; k += 4 )
|
||||
s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] +
|
||||
@@ -3357,7 +3561,7 @@ void HOGDescriptor::detectROI(const cv::Mat& img, const std::vector<cv::Point> &
|
||||
double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0;
|
||||
std::vector<float> blockHist(blockHistogramSize);
|
||||
|
||||
#if CV_SSE2
|
||||
#if CV_SSE2 || CV_NEON
|
||||
float partSum[4];
|
||||
#endif
|
||||
|
||||
@@ -3401,6 +3605,23 @@ void HOGDescriptor::detectROI(const cv::Mat& img, const std::vector<cv::Point> &
|
||||
double t0 = partSum[0] + partSum[1];
|
||||
double t1 = partSum[2] + partSum[3];
|
||||
s += t0 + t1;
|
||||
#elif CV_NEON
|
||||
float32x4_t _vec = vld1q_f32(vec);
|
||||
float32x4_t _svmVec = vld1q_f32(svmVec);
|
||||
float32x4_t sum = vmulq_f32(_svmVec, _vec);
|
||||
|
||||
for( k = 4; k <= blockHistogramSize - 4; k += 4 )
|
||||
{
|
||||
_vec = vld1q_f32(vec + k);
|
||||
_svmVec = vld1q_f32(svmVec + k);
|
||||
|
||||
sum = vaddq_f32(sum, vmulq_f32(_vec, _svmVec));
|
||||
}
|
||||
|
||||
vst1q_f32(partSum, sum);
|
||||
double t0 = partSum[0] + partSum[1];
|
||||
double t1 = partSum[2] + partSum[3];
|
||||
s += t0 + t1;
|
||||
#else
|
||||
for( k = 0; k <= blockHistogramSize - 4; k += 4 )
|
||||
s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] +
|
||||
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
CV_Assert(log_response.rows == LDR_SIZE && log_response.cols == 1 &&
|
||||
log_response.channels() == channels);
|
||||
|
||||
Mat exp_values(times);
|
||||
Mat exp_values(times.clone());
|
||||
log(exp_values, exp_values);
|
||||
|
||||
result = Mat::zeros(size, CV_32FCC);
|
||||
|
||||
+34
-20
@@ -1,11 +1,15 @@
|
||||
# This file is included from a subdirectory
|
||||
set(PYTHON_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../")
|
||||
|
||||
# try to use dynamic symbols linking with libpython.so
|
||||
set(OPENCV_FORCE_PYTHON_LIBS OFF CACHE BOOL "")
|
||||
string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}")
|
||||
|
||||
ocv_add_module(${MODULE_NAME} BINDINGS)
|
||||
|
||||
ocv_module_include_directories(
|
||||
"${PYTHON_INCLUDE_PATH}"
|
||||
${PYTHON_NUMPY_INCLUDE_DIRS}
|
||||
"${${PYTHON}_INCLUDE_PATH}"
|
||||
${${PYTHON}_NUMPY_INCLUDE_DIRS}
|
||||
"${PYTHON_SOURCE_DIR}/src2"
|
||||
)
|
||||
|
||||
@@ -42,7 +46,7 @@ set(cv2_generated_hdrs
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}")
|
||||
add_custom_command(
|
||||
OUTPUT ${cv2_generated_hdrs}
|
||||
COMMAND ${PYTHON_EXECUTABLE} "${PYTHON_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt"
|
||||
COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${PYTHON_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${PYTHON}"
|
||||
DEPENDS ${PYTHON_SOURCE_DIR}/src2/gen2.py
|
||||
DEPENDS ${PYTHON_SOURCE_DIR}/src2/hdr_parser.py
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/headers.txt
|
||||
@@ -50,21 +54,28 @@ add_custom_command(
|
||||
|
||||
ocv_add_library(${the_module} MODULE ${PYTHON_SOURCE_DIR}/src2/cv2.cpp ${cv2_generated_hdrs})
|
||||
|
||||
if(PYTHON_DEBUG_LIBRARIES AND NOT PYTHON_LIBRARIES MATCHES "optimized.*debug")
|
||||
ocv_target_link_libraries(${the_module} debug ${PYTHON_DEBUG_LIBRARIES} optimized ${PYTHON_LIBRARIES})
|
||||
else()
|
||||
if(APPLE)
|
||||
set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
||||
if(APPLE)
|
||||
set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
||||
elseif(WIN32 OR OPENCV_FORCE_PYTHON_LIBS)
|
||||
if(${PYTHON}_DEBUG_LIBRARIES AND NOT ${PYTHON}_LIBRARIES MATCHES "optimized.*debug")
|
||||
ocv_target_link_libraries(${the_module} debug ${${PYTHON}_DEBUG_LIBRARIES} optimized ${${PYTHON}_LIBRARIES})
|
||||
else()
|
||||
ocv_target_link_libraries(${the_module} ${PYTHON_LIBRARIES})
|
||||
ocv_target_link_libraries(${the_module} ${${PYTHON}_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
ocv_target_link_libraries(${the_module} ${OPENCV_MODULE_${the_module}_DEPS})
|
||||
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SO'))"
|
||||
RESULT_VARIABLE PYTHON_CVPY_PROCESS
|
||||
OUTPUT_VARIABLE CVPY_SUFFIX
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(DEFINED ${PYTHON}_CVPY_SUFFIX)
|
||||
set(CVPY_SUFFIX "${${PYTHON}_CVPY_SUFFIX}")
|
||||
else()
|
||||
execute_process(COMMAND ${${PYTHON}_EXECUTABLE} -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SO'))"
|
||||
RESULT_VARIABLE PYTHON_CVPY_PROCESS
|
||||
OUTPUT_VARIABLE CVPY_SUFFIX
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT PYTHON_CVPY_PROCESS EQUAL 0)
|
||||
set(CVPY_SUFFIX ".so")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(${the_module} PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${LIBRARY_OUTPUT_PATH}/${MODULE_INSTALL_SUBDIR}"
|
||||
@@ -96,7 +107,7 @@ if(MSVC AND NOT BUILD_SHARED_LIBS)
|
||||
set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG")
|
||||
endif()
|
||||
|
||||
if(MSVC AND NOT PYTHON_DEBUG_LIBRARIES)
|
||||
if(MSVC AND NOT ${PYTHON}_DEBUG_LIBRARIES)
|
||||
set(PYTHON_INSTALL_CONFIGURATIONS CONFIGURATIONS Release)
|
||||
else()
|
||||
set(PYTHON_INSTALL_CONFIGURATIONS "")
|
||||
@@ -105,19 +116,22 @@ endif()
|
||||
if(WIN32)
|
||||
set(PYTHON_INSTALL_ARCHIVE "")
|
||||
else()
|
||||
set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python)
|
||||
set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${${PYTHON}_PACKAGES_PATH} COMPONENT python)
|
||||
endif()
|
||||
|
||||
if(NOT INSTALL_CREATE_DISTRIB)
|
||||
if(NOT INSTALL_CREATE_DISTRIB AND DEFINED ${PYTHON}_PACKAGES_PATH)
|
||||
set(__dst "${${PYTHON}_PACKAGES_PATH}")
|
||||
install(TARGETS ${the_module} OPTIONAL
|
||||
${PYTHON_INSTALL_CONFIGURATIONS}
|
||||
RUNTIME DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python
|
||||
LIBRARY DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python
|
||||
RUNTIME DESTINATION "${__dst}" COMPONENT python
|
||||
LIBRARY DESTINATION "${__dst}" COMPONENT python
|
||||
${PYTHON_INSTALL_ARCHIVE}
|
||||
)
|
||||
else()
|
||||
if(DEFINED PYTHON_VERSION_MAJOR)
|
||||
set(__ver "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}")
|
||||
if(DEFINED ${PYTHON}_VERSION_MAJOR)
|
||||
set(__ver "${${PYTHON}_VERSION_MAJOR}.${${PYTHON}_VERSION_MINOR}")
|
||||
elseif(DEFINED ${PYTHON}_VERSION_STRING)
|
||||
set(__ver "${${PYTHON}_VERSION_STRING}")
|
||||
else()
|
||||
set(__ver "unknown")
|
||||
endif()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if(NOT PYTHON2LIBS_FOUND OR NOT PYTHON2_NUMPY_INCLUDE_DIRS)
|
||||
if(NOT PYTHON2_INCLUDE_PATH OR NOT PYTHON2_NUMPY_INCLUDE_DIRS)
|
||||
ocv_module_disable(python2)
|
||||
endif()
|
||||
|
||||
@@ -7,24 +7,9 @@ set(MODULE_NAME python2)
|
||||
# Buildbot requires Python 2 to be in root lib dir
|
||||
set(MODULE_INSTALL_SUBDIR "")
|
||||
|
||||
set(PYTHON_INCLUDE_PATH ${PYTHON2_INCLUDE_PATH})
|
||||
set(PYTHON_NUMPY_INCLUDE_DIRS ${PYTHON2_NUMPY_INCLUDE_DIRS})
|
||||
set(PYTHON_EXECUTABLE ${PYTHON2_EXECUTABLE})
|
||||
set(PYTHON_DEBUG_LIBRARIES ${PYTHON2_DEBUG_LIBRARIES})
|
||||
set(PYTHON_LIBRARIES ${PYTHON2_LIBRARIES})
|
||||
set(PYTHON_PACKAGES_PATH ${PYTHON2_PACKAGES_PATH})
|
||||
set(PYTHON_VERSION_MAJOR ${PYTHON2_VERSION_MAJOR})
|
||||
set(PYTHON_VERSION_MINOR ${PYTHON2_VERSION_MINOR})
|
||||
set(PYTHON PYTHON2)
|
||||
|
||||
include(../common.cmake)
|
||||
|
||||
unset(MODULE_NAME)
|
||||
unset(MODULE_INSTALL_SUBDIR)
|
||||
unset(PYTHON_INCLUDE_PATH)
|
||||
unset(PYTHON_NUMPY_INCLUDE_DIRS)
|
||||
unset(PYTHON_EXECUTABLE)
|
||||
unset(PYTHON_DEBUG_LIBRARIES)
|
||||
unset(PYTHON_LIBRARIES)
|
||||
unset(PYTHON_PACKAGES_PATH)
|
||||
unset(PYTHON_VERSION_MAJOR)
|
||||
unset(PYTHON_VERSION_MINOR)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if(NOT PYTHON3LIBS_FOUND OR NOT PYTHON3_NUMPY_INCLUDE_DIRS)
|
||||
if(NOT PYTHON3_INCLUDE_PATH OR NOT PYTHON3_NUMPY_INCLUDE_DIRS)
|
||||
ocv_module_disable(python3)
|
||||
endif()
|
||||
|
||||
@@ -6,24 +6,9 @@ set(the_description "The python3 bindings")
|
||||
set(MODULE_NAME python3)
|
||||
set(MODULE_INSTALL_SUBDIR python3)
|
||||
|
||||
set(PYTHON_INCLUDE_PATH ${PYTHON3_INCLUDE_PATH})
|
||||
set(PYTHON_NUMPY_INCLUDE_DIRS ${PYTHON3_NUMPY_INCLUDE_DIRS})
|
||||
set(PYTHON_EXECUTABLE ${PYTHON3_EXECUTABLE})
|
||||
set(PYTHON_DEBUG_LIBRARIES ${PYTHON3_DEBUG_LIBRARIES})
|
||||
set(PYTHON_LIBRARIES ${PYTHON3_LIBRARIES})
|
||||
set(PYTHON_PACKAGES_PATH ${PYTHON3_PACKAGES_PATH})
|
||||
set(PYTHON_VERSION_MAJOR ${PYTHON3_VERSION_MAJOR})
|
||||
set(PYTHON_VERSION_MINOR ${PYTHON3_VERSION_MINOR})
|
||||
set(PYTHON PYTHON3)
|
||||
|
||||
include(../common.cmake)
|
||||
|
||||
unset(MODULE_NAME)
|
||||
unset(MODULE_INSTALL_SUBDIR)
|
||||
unset(PYTHON_INCLUDE_PATH)
|
||||
unset(PYTHON_NUMPY_INCLUDE_DIRS)
|
||||
unset(PYTHON_EXECUTABLE)
|
||||
unset(PYTHON_DEBUG_LIBRARIES)
|
||||
unset(PYTHON_LIBRARIES)
|
||||
unset(PYTHON_PACKAGES_PATH)
|
||||
unset(PYTHON_VERSION_MAJOR)
|
||||
unset(PYTHON_VERSION_MINOR)
|
||||
|
||||
@@ -44,6 +44,14 @@ gen_template_func_body = Template("""$code_decl
|
||||
""")
|
||||
|
||||
py_major_version = sys.version_info[0]
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 3:
|
||||
if sys.argv[3] == 'PYTHON3':
|
||||
py_major_version = 3
|
||||
elif sys.argv[3] == 'PYTHON2':
|
||||
py_major_version = 2
|
||||
else:
|
||||
raise Exception('Incorrect argument: expected PYTHON2 or PYTHON3, received: ' + sys.argv[3])
|
||||
if py_major_version >= 3:
|
||||
head_init_str = "PyVarObject_HEAD_INIT(&PyType_Type, 0)"
|
||||
else:
|
||||
|
||||
@@ -58,7 +58,7 @@ def deskew(img):
|
||||
|
||||
class StatModel(object):
|
||||
def load(self, fn):
|
||||
self.model.load(fn) # Known bug: https://github.com/Itseez/opencv/issues/4969
|
||||
self.model.load(fn) # Known bug: https://github.com/opencv/opencv/issues/4969
|
||||
def save(self, fn):
|
||||
self.model.save(fn)
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class gaussian_mix_test(NewOpenCVTests):
|
||||
em.setCovarianceMatrixType(cv2.ml.EM_COV_MAT_GENERIC)
|
||||
em.trainEM(points)
|
||||
means = em.getMeans()
|
||||
covs = em.getCovs() # Known bug: https://github.com/Itseez/opencv/pull/4232
|
||||
covs = em.getCovs() # Known bug: https://github.com/opencv/opencv/pull/4232
|
||||
found_distrs = zip(means, covs)
|
||||
|
||||
matches_count = 0
|
||||
|
||||
@@ -21,7 +21,7 @@ class NewOpenCVTests(unittest.TestCase):
|
||||
repoPath = None
|
||||
extraTestDataPath = None
|
||||
# github repository url
|
||||
repoUrl = 'https://raw.github.com/Itseez/opencv/master'
|
||||
repoUrl = 'https://raw.github.com/opencv/opencv/master'
|
||||
|
||||
def get_sample(self, filename, iscolor = cv2.IMREAD_COLOR):
|
||||
if not filename in self.image_cache:
|
||||
|
||||
@@ -46,56 +46,6 @@
|
||||
#include <list>
|
||||
#include "opencv2/core.hpp"
|
||||
|
||||
#ifndef ENABLE_LOG
|
||||
#define ENABLE_LOG 0
|
||||
#endif
|
||||
|
||||
// TODO remove LOG macros, add logging class
|
||||
#if ENABLE_LOG
|
||||
#ifdef ANDROID
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <android/log.h>
|
||||
#define LOG_STITCHING_MSG(msg) \
|
||||
do { \
|
||||
Stringstream _os; \
|
||||
_os << msg; \
|
||||
__android_log_print(ANDROID_LOG_DEBUG, "STITCHING", "%s", _os.str().c_str()); \
|
||||
} while(0);
|
||||
#else
|
||||
#include <iostream>
|
||||
#define LOG_STITCHING_MSG(msg) for(;;) { std::cout << msg; std::cout.flush(); break; }
|
||||
#endif
|
||||
#else
|
||||
#define LOG_STITCHING_MSG(msg)
|
||||
#endif
|
||||
|
||||
#define LOG_(_level, _msg) \
|
||||
for(;;) \
|
||||
{ \
|
||||
using namespace std; \
|
||||
if ((_level) >= ::cv::detail::stitchingLogLevel()) \
|
||||
{ \
|
||||
LOG_STITCHING_MSG(_msg); \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
||||
#define LOG(msg) LOG_(1, msg)
|
||||
#define LOG_CHAT(msg) LOG_(0, msg)
|
||||
|
||||
#define LOGLN(msg) LOG(msg << std::endl)
|
||||
#define LOGLN_CHAT(msg) LOG_CHAT(msg << std::endl)
|
||||
|
||||
//#if DEBUG_LOG_CHAT
|
||||
// #define LOG_CHAT(msg) LOG(msg)
|
||||
// #define LOGLN_CHAT(msg) LOGLN(msg)
|
||||
//#else
|
||||
// #define LOG_CHAT(msg) do{}while(0)
|
||||
// #define LOGLN_CHAT(msg) do{}while(0)
|
||||
//#endif
|
||||
|
||||
namespace cv {
|
||||
namespace detail {
|
||||
|
||||
|
||||
@@ -99,4 +99,6 @@
|
||||
# include "opencv2/stitching/stitching_tegra.hpp"
|
||||
#endif
|
||||
|
||||
#include "util_log.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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_STITCHING_UTIL_LOG_HPP__
|
||||
#define __OPENCV_STITCHING_UTIL_LOG_HPP__
|
||||
|
||||
#ifndef ENABLE_LOG
|
||||
#define ENABLE_LOG 0
|
||||
#endif
|
||||
|
||||
// TODO remove LOG macros, add logging class
|
||||
#if ENABLE_LOG
|
||||
#ifdef ANDROID
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <android/log.h>
|
||||
#define LOG_STITCHING_MSG(msg) \
|
||||
do { \
|
||||
Stringstream _os; \
|
||||
_os << msg; \
|
||||
__android_log_print(ANDROID_LOG_DEBUG, "STITCHING", "%s", _os.str().c_str()); \
|
||||
} while(0);
|
||||
#else
|
||||
#include <iostream>
|
||||
#define LOG_STITCHING_MSG(msg) for(;;) { std::cout << msg; std::cout.flush(); break; }
|
||||
#endif
|
||||
#else
|
||||
#define LOG_STITCHING_MSG(msg)
|
||||
#endif
|
||||
|
||||
#define LOG_(_level, _msg) \
|
||||
for(;;) \
|
||||
{ \
|
||||
using namespace std; \
|
||||
if ((_level) >= ::cv::detail::stitchingLogLevel()) \
|
||||
{ \
|
||||
LOG_STITCHING_MSG(_msg); \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
||||
#define LOG(msg) LOG_(1, msg)
|
||||
#define LOG_CHAT(msg) LOG_(0, msg)
|
||||
|
||||
#define LOGLN(msg) LOG(msg << std::endl)
|
||||
#define LOGLN_CHAT(msg) LOG_CHAT(msg << std::endl)
|
||||
|
||||
//#if DEBUG_LOG_CHAT
|
||||
// #define LOG_CHAT(msg) LOG(msg)
|
||||
// #define LOGLN_CHAT(msg) LOGLN(msg)
|
||||
//#else
|
||||
// #define LOG_CHAT(msg) do{}while(0)
|
||||
// #define LOGLN_CHAT(msg) do{}while(0)
|
||||
//#endif
|
||||
|
||||
#endif // __OPENCV_STITCHING_UTIL_LOG_HPP__
|
||||
@@ -349,8 +349,8 @@ IMPLEMENT_PARAM_CLASS(Channels, int)
|
||||
#define OCL_TEST_F(name, ...) typedef name OCL_##name; TEST_F(OCL_##name, __VA_ARGS__)
|
||||
#define OCL_TEST(name, ...) TEST(OCL_##name, __VA_ARGS__)
|
||||
|
||||
#define OCL_OFF(fn) cv::ocl::setUseOpenCL(false); fn
|
||||
#define OCL_ON(fn) cv::ocl::setUseOpenCL(true); fn
|
||||
#define OCL_OFF(...) cv::ocl::setUseOpenCL(false); __VA_ARGS__ ;
|
||||
#define OCL_ON(...) cv::ocl::setUseOpenCL(true); __VA_ARGS__ ;
|
||||
|
||||
#define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F)
|
||||
#define OCL_ALL_CHANNELS Values(1, 2, 3, 4)
|
||||
|
||||
@@ -3064,6 +3064,9 @@ void printVersionInfo(bool useStdOut)
|
||||
#if CV_NEON
|
||||
if (checkHardwareSupport(CV_CPU_NEON)) cpu_features += " neon";
|
||||
#endif
|
||||
#if CV_FP16
|
||||
if (checkHardwareSupport(CV_CPU_FP16)) cpu_features += " fp16";
|
||||
#endif
|
||||
|
||||
cpu_features.erase(0, 1); // erase initial space
|
||||
|
||||
|
||||
@@ -397,6 +397,27 @@ public:
|
||||
CV_WRAP virtual void collectGarbage() = 0;
|
||||
};
|
||||
|
||||
/** @brief Base interface for sparse optical flow algorithms.
|
||||
*/
|
||||
class CV_EXPORTS_W SparseOpticalFlow : public Algorithm
|
||||
{
|
||||
public:
|
||||
/** @brief Calculates a sparse optical flow.
|
||||
|
||||
@param prevImg First input image.
|
||||
@param nextImg Second input image of the same size and the same type as prevImg.
|
||||
@param prevPts Vector of 2D points for which the flow needs to be found.
|
||||
@param nextPts Output vector of 2D points containing the calculated new positions of input features in the second image.
|
||||
@param status Output status vector. Each element of the vector is set to 1 if the
|
||||
flow for the corresponding features has been found. Otherwise, it is set to 0.
|
||||
@param err Optional output vector that contains error response for each point (inverse confidence).
|
||||
*/
|
||||
CV_WRAP virtual void calc(InputArray prevImg, InputArray nextImg,
|
||||
InputArray prevPts, InputOutputArray nextPts,
|
||||
OutputArray status,
|
||||
OutputArray err = cv::noArray()) = 0;
|
||||
};
|
||||
|
||||
/** @brief "Dual TV L1" Optical Flow Algorithm.
|
||||
|
||||
The class implements the "Dual TV L1" optical flow algorithm described in @cite Zach2007 and
|
||||
@@ -502,12 +523,102 @@ public:
|
||||
virtual int getMedianFiltering() const = 0;
|
||||
/** @copybrief getMedianFiltering @see getMedianFiltering */
|
||||
virtual void setMedianFiltering(int val) = 0;
|
||||
|
||||
/** @brief Creates instance of cv::DualTVL1OpticalFlow*/
|
||||
static Ptr<DualTVL1OpticalFlow> create(
|
||||
double tau = 0.25,
|
||||
double lambda = 0.15,
|
||||
double theta = 0.3,
|
||||
int nscales = 5,
|
||||
int warps = 5,
|
||||
double epsilon = 0.01,
|
||||
int innnerIterations = 30,
|
||||
int outerIterations = 10,
|
||||
double scaleStep = 0.8,
|
||||
double gamma = 0.0,
|
||||
int medianFiltering = 5,
|
||||
bool useInitialFlow = false);
|
||||
};
|
||||
|
||||
/** @brief Creates instance of cv::DenseOpticalFlow
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<DualTVL1OpticalFlow> createOptFlow_DualTVL1();
|
||||
|
||||
/** @brief Class computing a dense optical flow using the Gunnar Farneback’s algorithm.
|
||||
*/
|
||||
class CV_EXPORTS_W FarnebackOpticalFlow : public DenseOpticalFlow
|
||||
{
|
||||
public:
|
||||
virtual int getNumLevels() const = 0;
|
||||
virtual void setNumLevels(int numLevels) = 0;
|
||||
|
||||
virtual double getPyrScale() const = 0;
|
||||
virtual void setPyrScale(double pyrScale) = 0;
|
||||
|
||||
virtual bool getFastPyramids() const = 0;
|
||||
virtual void setFastPyramids(bool fastPyramids) = 0;
|
||||
|
||||
virtual int getWinSize() const = 0;
|
||||
virtual void setWinSize(int winSize) = 0;
|
||||
|
||||
virtual int getNumIters() const = 0;
|
||||
virtual void setNumIters(int numIters) = 0;
|
||||
|
||||
virtual int getPolyN() const = 0;
|
||||
virtual void setPolyN(int polyN) = 0;
|
||||
|
||||
virtual double getPolySigma() const = 0;
|
||||
virtual void setPolySigma(double polySigma) = 0;
|
||||
|
||||
virtual int getFlags() const = 0;
|
||||
virtual void setFlags(int flags) = 0;
|
||||
|
||||
static Ptr<FarnebackOpticalFlow> create(
|
||||
int numLevels = 5,
|
||||
double pyrScale = 0.5,
|
||||
bool fastPyramids = false,
|
||||
int winSize = 13,
|
||||
int numIters = 10,
|
||||
int polyN = 5,
|
||||
double polySigma = 1.1,
|
||||
int flags = 0);
|
||||
};
|
||||
|
||||
|
||||
/** @brief Class used for calculating a sparse optical flow.
|
||||
|
||||
The class can calculate an optical flow for a sparse feature set using the
|
||||
iterative Lucas-Kanade method with pyramids.
|
||||
|
||||
@sa calcOpticalFlowPyrLK
|
||||
|
||||
*/
|
||||
class CV_EXPORTS SparsePyrLKOpticalFlow : public SparseOpticalFlow
|
||||
{
|
||||
public:
|
||||
virtual Size getWinSize() const = 0;
|
||||
virtual void setWinSize(Size winSize) = 0;
|
||||
|
||||
virtual int getMaxLevel() const = 0;
|
||||
virtual void setMaxLevel(int maxLevel) = 0;
|
||||
|
||||
virtual TermCriteria getTermCriteria() const = 0;
|
||||
virtual void setTermCriteria(TermCriteria& crit) = 0;
|
||||
|
||||
virtual int getFlags() const = 0;
|
||||
virtual void setFlags(int flags) = 0;
|
||||
|
||||
virtual double getMinEigThreshold() const = 0;
|
||||
virtual void setMinEigThreshold(double minEigThreshold) = 0;
|
||||
|
||||
static Ptr<SparsePyrLKOpticalFlow> create(
|
||||
Size winSize = Size(21, 21),
|
||||
int maxLevel = 3, TermCriteria crit =
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01),
|
||||
int flags = 0,
|
||||
double minEigThreshold = 1e-4);
|
||||
};
|
||||
|
||||
//! @} video_track
|
||||
|
||||
} // cv
|
||||
|
||||
@@ -837,10 +837,11 @@ int cv::buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid, Si
|
||||
return maxLevel;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
namespace cv
|
||||
{
|
||||
class PyrLKOpticalFlow
|
||||
namespace
|
||||
{
|
||||
class SparsePyrLKOpticalFlowImpl : public SparsePyrLKOpticalFlow
|
||||
{
|
||||
struct dim3
|
||||
{
|
||||
@@ -848,17 +849,40 @@ namespace cv
|
||||
dim3() : x(0), y(0), z(0) { }
|
||||
};
|
||||
public:
|
||||
PyrLKOpticalFlow()
|
||||
SparsePyrLKOpticalFlowImpl(Size winSize_ = Size(21,21),
|
||||
int maxLevel_ = 3,
|
||||
TermCriteria criteria_ = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01),
|
||||
int flags_ = 0,
|
||||
double minEigThreshold_ = 1e-4) :
|
||||
winSize(winSize_), maxLevel(maxLevel_), criteria(criteria_), flags(flags_), minEigThreshold(minEigThreshold_)
|
||||
#ifdef HAVE_OPENCL
|
||||
, iters(criteria_.maxCount), derivLambda(criteria_.epsilon), useInitialFlow(0 != (flags_ & OPTFLOW_LK_GET_MIN_EIGENVALS)), waveSize(0)
|
||||
#endif
|
||||
{
|
||||
winSize = Size(21, 21);
|
||||
maxLevel = 3;
|
||||
iters = 30;
|
||||
derivLambda = 0.5;
|
||||
useInitialFlow = false;
|
||||
|
||||
waveSize = 0;
|
||||
}
|
||||
|
||||
virtual Size getWinSize() const {return winSize;}
|
||||
virtual void setWinSize(Size winSize_){winSize = winSize_;}
|
||||
|
||||
virtual int getMaxLevel() const {return maxLevel;}
|
||||
virtual void setMaxLevel(int maxLevel_){maxLevel = maxLevel_;}
|
||||
|
||||
virtual TermCriteria getTermCriteria() const {return criteria;}
|
||||
virtual void setTermCriteria(TermCriteria& crit_){criteria=crit_;}
|
||||
|
||||
virtual int getFlags() const {return flags; }
|
||||
virtual void setFlags(int flags_){flags=flags_;}
|
||||
|
||||
virtual double getMinEigThreshold() const {return minEigThreshold;}
|
||||
virtual void setMinEigThreshold(double minEigThreshold_){minEigThreshold=minEigThreshold_;}
|
||||
|
||||
virtual void calc(InputArray prevImg, InputArray nextImg,
|
||||
InputArray prevPts, InputOutputArray nextPts,
|
||||
OutputArray status,
|
||||
OutputArray err = cv::noArray());
|
||||
|
||||
private:
|
||||
#ifdef HAVE_OPENCL
|
||||
bool checkParam()
|
||||
{
|
||||
iters = std::min(std::max(iters, 0), 100);
|
||||
@@ -930,14 +954,17 @@ namespace cv
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
Size winSize;
|
||||
int maxLevel;
|
||||
TermCriteria criteria;
|
||||
int flags;
|
||||
double minEigThreshold;
|
||||
#ifdef HAVE_OPENCL
|
||||
int iters;
|
||||
double derivLambda;
|
||||
bool useInitialFlow;
|
||||
|
||||
private:
|
||||
int waveSize;
|
||||
bool initWaveSize()
|
||||
{
|
||||
@@ -1017,15 +1044,11 @@ namespace cv
|
||||
{
|
||||
return (cv::ocl::Device::TYPE_CPU == cv::ocl::Device::getDefault().type());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg,
|
||||
InputArray _prevPts, InputOutputArray _nextPts,
|
||||
OutputArray _status, OutputArray _err,
|
||||
Size winSize, int maxLevel,
|
||||
TermCriteria criteria,
|
||||
int flags/*, double minEigThreshold*/ )
|
||||
bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg,
|
||||
InputArray _prevPts, InputOutputArray _nextPts,
|
||||
OutputArray _status, OutputArray _err)
|
||||
{
|
||||
if (0 != (OPTFLOW_LK_GET_MIN_EIGENVALS & flags))
|
||||
return false;
|
||||
@@ -1045,7 +1068,6 @@ namespace cv
|
||||
if ((1 != _prevPts.size().height) && (1 != _prevPts.size().width))
|
||||
return false;
|
||||
size_t npoints = _prevPts.total();
|
||||
bool useInitialFlow = (0 != (flags & OPTFLOW_USE_INITIAL_FLOW));
|
||||
if (useInitialFlow)
|
||||
{
|
||||
if (_nextPts.empty() || _nextPts.type() != CV_32FC2 || (!_prevPts.isContinuous()))
|
||||
@@ -1060,14 +1082,7 @@ namespace cv
|
||||
_nextPts.create(_prevPts.size(), _prevPts.type());
|
||||
}
|
||||
|
||||
PyrLKOpticalFlow opticalFlow;
|
||||
opticalFlow.winSize = winSize;
|
||||
opticalFlow.maxLevel = maxLevel;
|
||||
opticalFlow.iters = criteria.maxCount;
|
||||
opticalFlow.derivLambda = criteria.epsilon;
|
||||
opticalFlow.useInitialFlow = useInitialFlow;
|
||||
|
||||
if (!opticalFlow.checkParam())
|
||||
if (!checkParam())
|
||||
return false;
|
||||
|
||||
UMat umatErr;
|
||||
@@ -1082,28 +1097,19 @@ namespace cv
|
||||
_status.create((int)npoints, 1, CV_8UC1);
|
||||
UMat umatNextPts = _nextPts.getUMat();
|
||||
UMat umatStatus = _status.getUMat();
|
||||
return opticalFlow.sparse(_prevImg.getUMat(), _nextImg.getUMat(), _prevPts.getUMat(), umatNextPts, umatStatus, umatErr);
|
||||
return sparse(_prevImg.getUMat(), _nextImg.getUMat(), _prevPts.getUMat(), umatNextPts, umatStatus, umatErr);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg,
|
||||
void SparsePyrLKOpticalFlowImpl::calc( InputArray _prevImg, InputArray _nextImg,
|
||||
InputArray _prevPts, InputOutputArray _nextPts,
|
||||
OutputArray _status, OutputArray _err,
|
||||
Size winSize, int maxLevel,
|
||||
TermCriteria criteria,
|
||||
int flags, double minEigThreshold )
|
||||
OutputArray _status, OutputArray _err)
|
||||
{
|
||||
#ifdef HAVE_OPENCL
|
||||
bool use_opencl = ocl::useOpenCL() &&
|
||||
(_prevImg.isUMat() || _nextImg.isUMat()) &&
|
||||
ocl::Image2D::isFormatSupported(CV_32F, 1, false);
|
||||
if ( use_opencl && ocl_calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err, winSize, maxLevel, criteria, flags/*, minEigThreshold*/))
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_OCL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CV_OCL_RUN(ocl::useOpenCL() &&
|
||||
(_prevImg.isUMat() || _nextImg.isUMat()) &&
|
||||
ocl::Image2D::isFormatSupported(CV_32F, 1, false),
|
||||
ocl_calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err))
|
||||
|
||||
Mat prevPtsMat = _prevPts.getMat();
|
||||
const int derivDepth = DataType<cv::detail::deriv_type>::depth;
|
||||
@@ -1262,6 +1268,22 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg,
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cv
|
||||
cv::Ptr<cv::SparsePyrLKOpticalFlow> cv::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, TermCriteria crit, int flags, double minEigThreshold){
|
||||
return makePtr<SparsePyrLKOpticalFlowImpl>(winSize,maxLevel,crit,flags,minEigThreshold);
|
||||
}
|
||||
void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg,
|
||||
InputArray _prevPts, InputOutputArray _nextPts,
|
||||
OutputArray _status, OutputArray _err,
|
||||
Size winSize, int maxLevel,
|
||||
TermCriteria criteria,
|
||||
int flags, double minEigThreshold )
|
||||
{
|
||||
Ptr<cv::SparsePyrLKOpticalFlow> optflow = cv::SparsePyrLKOpticalFlow::create(winSize,maxLevel,criteria,flags,minEigThreshold);
|
||||
optflow->calc(_prevImg,_nextImg,_prevPts,_nextPts,_status,_err);
|
||||
}
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
|
||||
+131
-102
@@ -583,39 +583,63 @@ FarnebackUpdateFlow_GaussianBlur( const Mat& _R0, const Mat& _R1,
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
namespace cv
|
||||
{
|
||||
class FarnebackOpticalFlow
|
||||
namespace
|
||||
{
|
||||
class FarnebackOpticalFlowImpl : public FarnebackOpticalFlow
|
||||
{
|
||||
public:
|
||||
FarnebackOpticalFlow()
|
||||
FarnebackOpticalFlowImpl(int numLevels=5, double pyrScale=0.5, bool fastPyramids=false, int winSize=13,
|
||||
int numIters=10, int polyN=5, double polySigma=1.1, int flags=0) :
|
||||
numLevels_(numLevels), pyrScale_(pyrScale), fastPyramids_(fastPyramids), winSize_(winSize),
|
||||
numIters_(numIters), polyN_(polyN), polySigma_(polySigma), flags_(flags)
|
||||
{
|
||||
numLevels = 5;
|
||||
pyrScale = 0.5;
|
||||
fastPyramids = false;
|
||||
winSize = 13;
|
||||
numIters = 10;
|
||||
polyN = 5;
|
||||
polySigma = 1.1;
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
int numLevels;
|
||||
double pyrScale;
|
||||
bool fastPyramids;
|
||||
int winSize;
|
||||
int numIters;
|
||||
int polyN;
|
||||
double polySigma;
|
||||
int flags;
|
||||
virtual int getNumLevels() const { return numLevels_; }
|
||||
virtual void setNumLevels(int numLevels) { numLevels_ = numLevels; }
|
||||
|
||||
virtual double getPyrScale() const { return pyrScale_; }
|
||||
virtual void setPyrScale(double pyrScale) { pyrScale_ = pyrScale; }
|
||||
|
||||
virtual bool getFastPyramids() const { return fastPyramids_; }
|
||||
virtual void setFastPyramids(bool fastPyramids) { fastPyramids_ = fastPyramids; }
|
||||
|
||||
virtual int getWinSize() const { return winSize_; }
|
||||
virtual void setWinSize(int winSize) { winSize_ = winSize; }
|
||||
|
||||
virtual int getNumIters() const { return numIters_; }
|
||||
virtual void setNumIters(int numIters) { numIters_ = numIters; }
|
||||
|
||||
virtual int getPolyN() const { return polyN_; }
|
||||
virtual void setPolyN(int polyN) { polyN_ = polyN; }
|
||||
|
||||
virtual double getPolySigma() const { return polySigma_; }
|
||||
virtual void setPolySigma(double polySigma) { polySigma_ = polySigma; }
|
||||
|
||||
virtual int getFlags() const { return flags_; }
|
||||
virtual void setFlags(int flags) { flags_ = flags; }
|
||||
|
||||
virtual void calc(InputArray I0, InputArray I1, InputOutputArray flow);
|
||||
|
||||
private:
|
||||
int numLevels_;
|
||||
double pyrScale_;
|
||||
bool fastPyramids_;
|
||||
int winSize_;
|
||||
int numIters_;
|
||||
int polyN_;
|
||||
double polySigma_;
|
||||
int flags_;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
bool operator ()(const UMat &frame0, const UMat &frame1, UMat &flowx, UMat &flowy)
|
||||
{
|
||||
CV_Assert(frame0.channels() == 1 && frame1.channels() == 1);
|
||||
CV_Assert(frame0.size() == frame1.size());
|
||||
CV_Assert(polyN == 5 || polyN == 7);
|
||||
CV_Assert(!fastPyramids || std::abs(pyrScale - 0.5) < 1e-6);
|
||||
CV_Assert(polyN_ == 5 || polyN_ == 7);
|
||||
CV_Assert(!fastPyramids_ || std::abs(pyrScale_ - 0.5) < 1e-6);
|
||||
|
||||
const int min_size = 32;
|
||||
|
||||
@@ -630,9 +654,9 @@ public:
|
||||
// Crop unnecessary levels
|
||||
double scale = 1;
|
||||
int numLevelsCropped = 0;
|
||||
for (; numLevelsCropped < numLevels; numLevelsCropped++)
|
||||
for (; numLevelsCropped < numLevels_; numLevelsCropped++)
|
||||
{
|
||||
scale *= pyrScale;
|
||||
scale *= pyrScale_;
|
||||
if (size.width*scale < min_size || size.height*scale < min_size)
|
||||
break;
|
||||
}
|
||||
@@ -640,7 +664,7 @@ public:
|
||||
frame0.convertTo(frames_[0], CV_32F);
|
||||
frame1.convertTo(frames_[1], CV_32F);
|
||||
|
||||
if (fastPyramids)
|
||||
if (fastPyramids_)
|
||||
{
|
||||
// Build Gaussian pyramids using pyrDown()
|
||||
pyramid0_.resize(numLevelsCropped + 1);
|
||||
@@ -654,13 +678,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
setPolynomialExpansionConsts(polyN, polySigma);
|
||||
setPolynomialExpansionConsts(polyN_, polySigma_);
|
||||
|
||||
for (int k = numLevelsCropped; k >= 0; k--)
|
||||
{
|
||||
scale = 1;
|
||||
for (int i = 0; i < k; i++)
|
||||
scale *= pyrScale;
|
||||
scale *= pyrScale_;
|
||||
|
||||
double sigma = (1./scale - 1) * 0.5;
|
||||
int smoothSize = cvRound(sigma*5) | 1;
|
||||
@@ -669,7 +693,7 @@ public:
|
||||
int width = cvRound(size.width*scale);
|
||||
int height = cvRound(size.height*scale);
|
||||
|
||||
if (fastPyramids)
|
||||
if (fastPyramids_)
|
||||
{
|
||||
width = pyramid0_[k].cols;
|
||||
height = pyramid0_[k].rows;
|
||||
@@ -688,7 +712,7 @@ public:
|
||||
|
||||
if (prevFlowX.empty())
|
||||
{
|
||||
if (flags & cv::OPTFLOW_USE_INITIAL_FLOW)
|
||||
if (flags_ & cv::OPTFLOW_USE_INITIAL_FLOW)
|
||||
{
|
||||
resize(flowx0, curFlowX, Size(width, height), 0, 0, INTER_LINEAR);
|
||||
resize(flowy0, curFlowY, Size(width, height), 0, 0, INTER_LINEAR);
|
||||
@@ -705,8 +729,8 @@ public:
|
||||
{
|
||||
resize(prevFlowX, curFlowX, Size(width, height), 0, 0, INTER_LINEAR);
|
||||
resize(prevFlowY, curFlowY, Size(width, height), 0, 0, INTER_LINEAR);
|
||||
multiply(1./pyrScale, curFlowX, curFlowX);
|
||||
multiply(1./pyrScale, curFlowY, curFlowY);
|
||||
multiply(1./pyrScale_, curFlowX, curFlowX);
|
||||
multiply(1./pyrScale_, curFlowY, curFlowY);
|
||||
}
|
||||
|
||||
UMat M = allocMatFromBuf(5*height, width, CV_32F, M_);
|
||||
@@ -717,7 +741,7 @@ public:
|
||||
allocMatFromBuf(5*height, width, CV_32F, R_[1])
|
||||
};
|
||||
|
||||
if (fastPyramids)
|
||||
if (fastPyramids_)
|
||||
{
|
||||
if (!polynomialExpansionOcl(pyramid0_[k], R[0]))
|
||||
return false;
|
||||
@@ -752,18 +776,18 @@ public:
|
||||
if (!updateMatricesOcl(curFlowX, curFlowY, R[0], R[1], M))
|
||||
return false;
|
||||
|
||||
if (flags & OPTFLOW_FARNEBACK_GAUSSIAN)
|
||||
setGaussianBlurKernel(winSize, winSize/2*0.3f);
|
||||
for (int i = 0; i < numIters; i++)
|
||||
if (flags_ & OPTFLOW_FARNEBACK_GAUSSIAN)
|
||||
setGaussianBlurKernel(winSize_, winSize_/2*0.3f);
|
||||
for (int i = 0; i < numIters_; i++)
|
||||
{
|
||||
if (flags & OPTFLOW_FARNEBACK_GAUSSIAN)
|
||||
if (flags_ & OPTFLOW_FARNEBACK_GAUSSIAN)
|
||||
{
|
||||
if (!updateFlow_gaussianBlur(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1))
|
||||
if (!updateFlow_gaussianBlur(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize_, i < numIters_-1))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!updateFlow_boxFilter(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1))
|
||||
if (!updateFlow_boxFilter(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize_, i < numIters_-1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -776,7 +800,9 @@ public:
|
||||
flowy = curFlowY;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void collectGarbage(){
|
||||
releaseMemory();
|
||||
}
|
||||
void releaseMemory()
|
||||
{
|
||||
frames_[0].release();
|
||||
@@ -898,15 +924,15 @@ private:
|
||||
#else
|
||||
size_t localsize[2] = { 256, 1};
|
||||
#endif
|
||||
size_t globalsize[2] = { DIVUP((size_t)src.cols, localsize[0] - 2*polyN) * localsize[0], (size_t)src.rows};
|
||||
size_t globalsize[2] = { DIVUP((size_t)src.cols, localsize[0] - 2*polyN_) * localsize[0], (size_t)src.rows};
|
||||
|
||||
#if 0
|
||||
const cv::ocl::Device &device = cv::ocl::Device::getDefault();
|
||||
bool useDouble = (0 != device.doubleFPConfig());
|
||||
|
||||
cv::String build_options = cv::format("-D polyN=%d -D USE_DOUBLE=%d", polyN, useDouble ? 1 : 0);
|
||||
cv::String build_options = cv::format("-D polyN=%d -D USE_DOUBLE=%d", polyN_, useDouble ? 1 : 0);
|
||||
#else
|
||||
cv::String build_options = cv::format("-D polyN=%d", polyN);
|
||||
cv::String build_options = cv::format("-D polyN=%d", polyN_);
|
||||
#endif
|
||||
ocl::Kernel kernel;
|
||||
if (!kernel.create("polynomialExpansion", cv::ocl::video::optical_flow_farneback_oclsrc, build_options))
|
||||
@@ -1036,60 +1062,43 @@ private:
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool calc_ocl( InputArray _prev0, InputArray _next0,
|
||||
InputOutputArray _flow0)
|
||||
{
|
||||
if ((5 != polyN_) && (7 != polyN_))
|
||||
return false;
|
||||
if (_next0.size() != _prev0.size())
|
||||
return false;
|
||||
int typePrev = _prev0.type();
|
||||
int typeNext = _next0.type();
|
||||
if ((1 != CV_MAT_CN(typePrev)) || (1 != CV_MAT_CN(typeNext)))
|
||||
return false;
|
||||
|
||||
std::vector<UMat> flowar;
|
||||
if (!_flow0.empty())
|
||||
split(_flow0, flowar);
|
||||
else
|
||||
{
|
||||
flowar.push_back(UMat());
|
||||
flowar.push_back(UMat());
|
||||
}
|
||||
if(!this->operator()(_prev0.getUMat(), _next0.getUMat(), flowar[0], flowar[1])){
|
||||
return false;
|
||||
}
|
||||
merge(flowar, _flow0);
|
||||
return true;
|
||||
}
|
||||
#else // HAVE_OPENCL
|
||||
virtual void collectGarbage(){}
|
||||
#endif
|
||||
};
|
||||
|
||||
static bool ocl_calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0,
|
||||
InputOutputArray _flow0, double pyr_scale, int levels, int winsize,
|
||||
int iterations, int poly_n, double poly_sigma, int flags )
|
||||
void FarnebackOpticalFlowImpl::calc(InputArray _prev0, InputArray _next0,
|
||||
InputOutputArray _flow0)
|
||||
{
|
||||
if ((5 != poly_n) && (7 != poly_n))
|
||||
return false;
|
||||
if (_next0.size() != _prev0.size())
|
||||
return false;
|
||||
int typePrev = _prev0.type();
|
||||
int typeNext = _next0.type();
|
||||
if ((1 != CV_MAT_CN(typePrev)) || (1 != CV_MAT_CN(typeNext)))
|
||||
return false;
|
||||
|
||||
FarnebackOpticalFlow opticalFlow;
|
||||
opticalFlow.numLevels = levels;
|
||||
opticalFlow.pyrScale = pyr_scale;
|
||||
opticalFlow.fastPyramids= false;
|
||||
opticalFlow.winSize = winsize;
|
||||
opticalFlow.numIters = iterations;
|
||||
opticalFlow.polyN = poly_n;
|
||||
opticalFlow.polySigma = poly_sigma;
|
||||
opticalFlow.flags = flags;
|
||||
|
||||
std::vector<UMat> flowar;
|
||||
if (!_flow0.empty())
|
||||
split(_flow0, flowar);
|
||||
else
|
||||
{
|
||||
flowar.push_back(UMat());
|
||||
flowar.push_back(UMat());
|
||||
}
|
||||
if (!opticalFlow(_prev0.getUMat(), _next0.getUMat(), flowar[0], flowar[1]))
|
||||
return false;
|
||||
merge(flowar, _flow0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_OPENCL
|
||||
|
||||
void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0,
|
||||
InputOutputArray _flow0, double pyr_scale, int levels, int winsize,
|
||||
int iterations, int poly_n, double poly_sigma, int flags )
|
||||
{
|
||||
#ifdef HAVE_OPENCL
|
||||
bool use_opencl = ocl::useOpenCL() && _flow0.isUMat();
|
||||
if( use_opencl && ocl_calcOpticalFlowFarneback(_prev0, _next0, _flow0, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags))
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_OCL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
CV_OCL_RUN(_flow0.isUMat() &&
|
||||
ocl::Image2D::isFormatSupported(CV_32F, 1, false),
|
||||
calc_ocl(_prev0,_next0,_flow0))
|
||||
Mat prev0 = _prev0.getMat(), next0 = _next0.getMat();
|
||||
const int min_size = 32;
|
||||
const Mat* img[2] = { &prev0, &next0 };
|
||||
@@ -1097,15 +1106,16 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0,
|
||||
int i, k;
|
||||
double scale;
|
||||
Mat prevFlow, flow, fimg;
|
||||
int levels = numLevels_;
|
||||
|
||||
CV_Assert( prev0.size() == next0.size() && prev0.channels() == next0.channels() &&
|
||||
prev0.channels() == 1 && pyr_scale < 1 );
|
||||
prev0.channels() == 1 && pyrScale_ < 1 );
|
||||
_flow0.create( prev0.size(), CV_32FC2 );
|
||||
Mat flow0 = _flow0.getMat();
|
||||
|
||||
for( k = 0, scale = 1; k < levels; k++ )
|
||||
{
|
||||
scale *= pyr_scale;
|
||||
scale *= pyrScale_;
|
||||
if( prev0.cols*scale < min_size || prev0.rows*scale < min_size )
|
||||
break;
|
||||
}
|
||||
@@ -1115,7 +1125,7 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0,
|
||||
for( k = levels; k >= 0; k-- )
|
||||
{
|
||||
for( i = 0, scale = 1; i < k; i++ )
|
||||
scale *= pyr_scale;
|
||||
scale *= pyrScale_;
|
||||
|
||||
double sigma = (1./scale-1)*0.5;
|
||||
int smooth_sz = cvRound(sigma*5)|1;
|
||||
@@ -1131,7 +1141,7 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0,
|
||||
|
||||
if( prevFlow.empty() )
|
||||
{
|
||||
if( flags & OPTFLOW_USE_INITIAL_FLOW )
|
||||
if( flags_ & OPTFLOW_USE_INITIAL_FLOW )
|
||||
{
|
||||
resize( flow0, flow, Size(width, height), 0, 0, INTER_AREA );
|
||||
flow *= scale;
|
||||
@@ -1142,7 +1152,7 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0,
|
||||
else
|
||||
{
|
||||
resize( prevFlow, flow, Size(width, height), 0, 0, INTER_LINEAR );
|
||||
flow *= 1./pyr_scale;
|
||||
flow *= 1./pyrScale_;
|
||||
}
|
||||
|
||||
Mat R[2], I, M;
|
||||
@@ -1151,19 +1161,38 @@ void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0,
|
||||
img[i]->convertTo(fimg, CV_32F);
|
||||
GaussianBlur(fimg, fimg, Size(smooth_sz, smooth_sz), sigma, sigma);
|
||||
resize( fimg, I, Size(width, height), INTER_LINEAR );
|
||||
FarnebackPolyExp( I, R[i], poly_n, poly_sigma );
|
||||
FarnebackPolyExp( I, R[i], polyN_, polySigma_ );
|
||||
}
|
||||
|
||||
FarnebackUpdateMatrices( R[0], R[1], flow, M, 0, flow.rows );
|
||||
|
||||
for( i = 0; i < iterations; i++ )
|
||||
for( i = 0; i < numIters_; i++ )
|
||||
{
|
||||
if( flags & OPTFLOW_FARNEBACK_GAUSSIAN )
|
||||
FarnebackUpdateFlow_GaussianBlur( R[0], R[1], flow, M, winsize, i < iterations - 1 );
|
||||
if( flags_ & OPTFLOW_FARNEBACK_GAUSSIAN )
|
||||
FarnebackUpdateFlow_GaussianBlur( R[0], R[1], flow, M, winSize_, i < numIters_ - 1 );
|
||||
else
|
||||
FarnebackUpdateFlow_Blur( R[0], R[1], flow, M, winsize, i < iterations - 1 );
|
||||
FarnebackUpdateFlow_Blur( R[0], R[1], flow, M, winSize_, i < numIters_ - 1 );
|
||||
}
|
||||
|
||||
prevFlow = flow;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
} // namespace cv
|
||||
|
||||
void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0,
|
||||
InputOutputArray _flow0, double pyr_scale, int levels, int winsize,
|
||||
int iterations, int poly_n, double poly_sigma, int flags )
|
||||
{
|
||||
Ptr<cv::FarnebackOpticalFlow> optflow;
|
||||
optflow = makePtr<FarnebackOpticalFlowImpl>(levels,pyr_scale,false,winsize,iterations,poly_n,poly_sigma,flags);
|
||||
optflow->calc(_prev0,_next0,_flow0);
|
||||
}
|
||||
|
||||
|
||||
cv::Ptr<cv::FarnebackOpticalFlow> cv::FarnebackOpticalFlow::create(int numLevels, double pyrScale, bool fastPyramids, int winSize,
|
||||
int numIters, int polyN, double polySigma, int flags)
|
||||
{
|
||||
return makePtr<FarnebackOpticalFlowImpl>(numLevels, pyrScale, fastPyramids, winSize,
|
||||
numIters, polyN, polySigma, flags);
|
||||
}
|
||||
|
||||
@@ -89,6 +89,17 @@ namespace {
|
||||
class OpticalFlowDual_TVL1 : public DualTVL1OpticalFlow
|
||||
{
|
||||
public:
|
||||
|
||||
OpticalFlowDual_TVL1(double tau_, double lambda_, double theta_, int nscales_, int warps_,
|
||||
double epsilon_, int innerIterations_, int outerIterations_,
|
||||
double scaleStep_, double gamma_, int medianFiltering_,
|
||||
bool useInitialFlow_) :
|
||||
tau(tau_), lambda(lambda_), theta(theta_), gamma(gamma_), nscales(nscales_),
|
||||
warps(warps_), epsilon(epsilon_), innerIterations(innerIterations_),
|
||||
outerIterations(outerIterations_), useInitialFlow(useInitialFlow_),
|
||||
scaleStep(scaleStep_), medianFiltering(medianFiltering_)
|
||||
{
|
||||
}
|
||||
OpticalFlowDual_TVL1();
|
||||
|
||||
void calc(InputArray I0, InputArray I1, InputOutputArray flow);
|
||||
@@ -1450,3 +1461,13 @@ Ptr<DualTVL1OpticalFlow> cv::createOptFlow_DualTVL1()
|
||||
{
|
||||
return makePtr<OpticalFlowDual_TVL1>();
|
||||
}
|
||||
|
||||
Ptr<DualTVL1OpticalFlow> cv::DualTVL1OpticalFlow::create(
|
||||
double tau, double lambda, double theta, int nscales, int warps,
|
||||
double epsilon, int innerIterations, int outerIterations, double scaleStep,
|
||||
double gamma, int medianFilter, bool useInitialFlow)
|
||||
{
|
||||
return makePtr<OpticalFlowDual_TVL1>(tau, lambda, theta, nscales, warps,
|
||||
epsilon, innerIterations, outerIterations,
|
||||
scaleStep, gamma, medianFilter, useInitialFlow);
|
||||
}
|
||||
|
||||
@@ -72,11 +72,11 @@ void CV_AccumBaseTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int depth = cvtest::randInt(rng) % 3, cn = cvtest::randInt(rng) & 1 ? 3 : 1;
|
||||
int accdepth = std::max((int)(cvtest::randInt(rng) % 2 + 1), depth);
|
||||
int depth = cvtest::randInt(rng) % 4, cn = cvtest::randInt(rng) & 1 ? 3 : 1;
|
||||
int accdepth = (int)(cvtest::randInt(rng) % 2 + 1);
|
||||
int i, input_count = (int)test_array[INPUT].size();
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
|
||||
depth = depth == 0 ? CV_8U : depth == 1 ? CV_32F : CV_64F;
|
||||
depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : depth == 2 ? CV_32F : CV_64F;
|
||||
accdepth = accdepth == 1 ? CV_32F : CV_64F;
|
||||
accdepth = MAX(accdepth, depth);
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ TEST(Video_calcOpticalFlowDual_TVL1, Regression)
|
||||
ASSERT_FALSE(frame2.empty());
|
||||
|
||||
Mat_<Point2f> flow;
|
||||
Ptr<DenseOpticalFlow> tvl1 = createOptFlow_DualTVL1();
|
||||
Ptr<DualTVL1OpticalFlow> tvl1 = cv::DualTVL1OpticalFlow::create();
|
||||
|
||||
tvl1->calc(frame1, frame2, flow);
|
||||
|
||||
|
||||
@@ -614,7 +614,7 @@ public:
|
||||
Also, when a connected camera is multi-head (for example, a stereo camera or a Kinect device), the
|
||||
correct way of retrieving data from it is to call VideoCapture::grab first and then call
|
||||
VideoCapture::retrieve one or more times with different values of the channel parameter. See
|
||||
<https://github.com/Itseez/opencv/tree/master/samples/cpp/openni_capture.cpp>
|
||||
<https://github.com/opencv/opencv/tree/master/samples/cpp/openni_capture.cpp>
|
||||
*/
|
||||
CV_WRAP virtual bool grab();
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined HAVE_FFMPEG && !defined WIN32
|
||||
#include "cap_ffmpeg_impl.hpp"
|
||||
#else
|
||||
@@ -59,6 +61,17 @@ static CvWriteFrame_Plugin icvWriteFrame_FFMPEG_p = 0;
|
||||
|
||||
static cv::Mutex _icvInitFFMPEG_mutex;
|
||||
|
||||
#if defined WIN32 || defined _WIN32
|
||||
static const HMODULE cv_GetCurrentModule()
|
||||
{
|
||||
HMODULE h = 0;
|
||||
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
reinterpret_cast<LPCTSTR>(cv_GetCurrentModule),
|
||||
&h);
|
||||
return h;
|
||||
}
|
||||
#endif
|
||||
|
||||
class icvInitFFMPEG
|
||||
{
|
||||
public:
|
||||
@@ -95,14 +108,39 @@ private:
|
||||
|
||||
icvFFOpenCV = LoadPackagedLibrary( module_name, 0 );
|
||||
# else
|
||||
const char* module_name = "opencv_ffmpeg"
|
||||
CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
|
||||
const std::wstring module_name = L"opencv_ffmpeg"
|
||||
CVAUX_STRW(CV_MAJOR_VERSION) CVAUX_STRW(CV_MINOR_VERSION) CVAUX_STRW(CV_SUBMINOR_VERSION)
|
||||
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
|
||||
"_64"
|
||||
L"_64"
|
||||
#endif
|
||||
".dll";
|
||||
L".dll";
|
||||
|
||||
icvFFOpenCV = LoadLibrary( module_name );
|
||||
const wchar_t* ffmpeg_env_path = _wgetenv(L"OPENCV_FFMPEG_DLL_DIR");
|
||||
std::wstring module_path =
|
||||
ffmpeg_env_path
|
||||
? ((std::wstring(ffmpeg_env_path) + L"\\") + module_name)
|
||||
: module_name;
|
||||
|
||||
icvFFOpenCV = LoadLibraryW(module_path.c_str());
|
||||
if(!icvFFOpenCV && !ffmpeg_env_path)
|
||||
{
|
||||
HMODULE m = cv_GetCurrentModule();
|
||||
if (m)
|
||||
{
|
||||
wchar_t path[MAX_PATH];
|
||||
size_t sz = GetModuleFileNameW(m, path, sizeof(path));
|
||||
if (sz > 0 && ERROR_SUCCESS == GetLastError())
|
||||
{
|
||||
wchar_t* s = wcsrchr(path, L'\\');
|
||||
if (s)
|
||||
{
|
||||
s[0] = 0;
|
||||
module_path = (std::wstring(path) + L"\\") + module_name;
|
||||
icvFFOpenCV = LoadLibraryW(module_path.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
if( icvFFOpenCV )
|
||||
|
||||
@@ -1135,11 +1135,7 @@ int CvCapture_FFMPEG::get_bitrate() const
|
||||
|
||||
double CvCapture_FFMPEG::get_fps() const
|
||||
{
|
||||
#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0)
|
||||
double fps = r2d(ic->streams[video_stream]->avg_frame_rate);
|
||||
#else
|
||||
double fps = r2d(ic->streams[video_stream]->r_frame_rate);
|
||||
#endif
|
||||
|
||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
|
||||
if (fps < eps_zero)
|
||||
|
||||
@@ -16,7 +16,7 @@ For Release: OpenCV-Linux Beta4 opencv-0.9.6
|
||||
Tested On: LMLBT44 with 8 video inputs
|
||||
Problems? Post your questions at answers.opencv.org,
|
||||
Report bugs at code.opencv.org,
|
||||
Submit your fixes at https://github.com/Itseez/opencv/
|
||||
Submit your fixes at https://github.com/opencv/opencv/
|
||||
Patched Comments:
|
||||
|
||||
TW: The cv cam utils that came with the initial release of OpenCV for LINUX Beta4
|
||||
|
||||
@@ -16,7 +16,7 @@ For Release: OpenCV-Linux Beta4 opencv-0.9.6
|
||||
Tested On: LMLBT44 with 8 video inputs
|
||||
Problems? Post your questions at answers.opencv.org,
|
||||
Report bugs at code.opencv.org,
|
||||
Submit your fixes at https://github.com/Itseez/opencv/
|
||||
Submit your fixes at https://github.com/opencv/opencv/
|
||||
Patched Comments:
|
||||
|
||||
TW: The cv cam utils that came with the initial release of OpenCV for LINUX Beta4
|
||||
|
||||
@@ -118,6 +118,9 @@ public:
|
||||
frame_s = Size(352, 288);
|
||||
else if( tag == VideoWriter::fourcc('H', '2', '6', '3') )
|
||||
frame_s = Size(704, 576);
|
||||
else if( tag == VideoWriter::fourcc('H', '2', '6', '4') )
|
||||
// OpenH264 1.5.0 has resolution limitations, so lets use DCI 4K resolution
|
||||
frame_s = Size(4096, 2160);
|
||||
/*else if( tag == CV_FOURCC('M', 'J', 'P', 'G') ||
|
||||
tag == CV_FOURCC('j', 'p', 'e', 'g') )
|
||||
frame_s = Size(1920, 1080);*/
|
||||
|
||||
Reference in New Issue
Block a user