1
0
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:
MYLS
2016-07-30 01:08:27 +08:00
196 changed files with 5398 additions and 1448 deletions
+464 -251
View File
@@ -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;
}
+4 -4
View File
@@ -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
+96
View File
@@ -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;
}
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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/>.
+10
View File
@@ -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
+7 -3
View File
@@ -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
+17 -9
View File
@@ -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
+1 -1
View File
@@ -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;
}
+4 -3
View File
@@ -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 );
+371
View File
@@ -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;
-6
View File
@@ -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() );
+2 -2
View File
@@ -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) );
-2
View File
@@ -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 );
+1
View File
@@ -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);
+7 -7
View File
@@ -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];
+10 -2
View File
@@ -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;
+80
View File
@@ -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));
}
+284
View File
@@ -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());
}
-270
View File
@@ -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:
}
+28 -2
View File
@@ -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());
}
+17
View File
@@ -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);
+1 -1
View File
@@ -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
+9 -3
View File
@@ -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();
}
}
+2 -2
View File
@@ -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,
+6 -6
View File
@@ -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
+1 -1
View File
@@ -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.
*/
+71 -49
View File
@@ -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;
}
}
+4 -2
View File
@@ -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);
+66 -18
View File
@@ -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 )
+6
View File
@@ -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)
+197
View File
@@ -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
+70
View File
@@ -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_*/
+7 -8
View File
@@ -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
+1
View File
@@ -54,5 +54,6 @@
#include "grfmt_webp.hpp"
#include "grfmt_hdr.hpp"
#include "grfmt_gdal.hpp"
#include "grfmt_gdcm.hpp"
#endif/*_GRFMTS_H_*/
+3
View File
@@ -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
View File
@@ -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 )
{
+4 -2
View File
@@ -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
View File
@@ -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);
}
+7 -7
View File
@@ -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;
+26 -21
View File
@@ -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
View File
@@ -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++ )
+17
View File
@@ -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
{
+30 -7
View File
@@ -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))));
+24 -3
View File
@@ -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. */
+70
View 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));
}
+1 -1
View File
@@ -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.
+223 -2
View File
@@ -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] +
+1 -1
View File
@@ -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
View File
@@ -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()
+2 -17
View File
@@ -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)
+2 -17
View File
@@ -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)
+8
View File
@@ -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:
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 {
+2
View File
@@ -99,4 +99,6 @@
# include "opencv2/stitching/stitching_tegra.hpp"
#endif
#include "util_log.hpp"
#endif
+58
View File
@@ -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__
+2 -2
View File
@@ -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)
+3
View File
@@ -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 Farnebacks 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
+67 -45
View File
@@ -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
View File
@@ -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);
}
+21
View File
@@ -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);
}
+3 -3
View File
@@ -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);
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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();
+43 -5
View File
@@ -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 )
-4
View File
@@ -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)
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+3
View File
@@ -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);*/