// Get an 8-bit equivalent of the 32-bit Float image.
// Returns a new image, so remember to call 'cvReleaseImage()' on the result.
IplImage* convertFloatImageToUcharImage(const IplImage *srcImg)
{
    IplImage *dstImg = 0;
    if ((srcImg) && (srcImg->width > 0 && srcImg->height > 0)) {
        
        // Spread the 32bit floating point pixels to fit within 8bit pixel range.
        double minVal, maxVal;
        cvMinMaxLoc(srcImg, &minVal, &maxVal);
        
        //cout << "FloatImage:(minV=" << minVal << ", maxV=" << maxVal << ")." << endl;
        
        // Deal with NaN and extreme values, since the DFT seems to give some NaN results.
        if (cvIsNaN(minVal) || minVal < -1e30)
            minVal = -1e30;
        if (cvIsNaN(maxVal) || maxVal > 1e30)
            maxVal = 1e30;
        if (maxVal-minVal == 0.0f)
            maxVal = minVal + 0.001;	// remove potential divide by zero errors.
        
        // Convert the format
        dstImg = cvCreateImage(cvSize(srcImg->width, srcImg->height), 8, 1);
        cvConvertScale(srcImg, dstImg, 255.0 / (maxVal - minVal), - minVal * 255.0 / (maxVal-minVal));
    }
    return dstImg;
}
Esempio n. 2
0
int CV_QueryHistTest::validate_test_results( int /*test_case_idx*/ )
{
    int code = CvTS::OK;
    int i, j, iters = values->cols;
    
    for( i = 0; i < iters; i++ )
    {
        float v = values->data.fl[i], v0 = values0->data.fl[i];

        if( cvIsNaN(v) || cvIsInf(v) )
        {
            ts->printf( CvTS::LOG, "The bin #%d has invalid value\n", i );
            code = CvTS::FAIL_INVALID_OUTPUT;
        }
        else if( fabs(v - v0) > FLT_EPSILON )
        {
            ts->printf( CvTS::LOG, "The bin #%d = %g, while it should be %g\n", i, v, v0 );
            code = CvTS::FAIL_BAD_ACCURACY;
        }

        if( code < 0 )
        {
            ts->printf( CvTS::LOG, "The bin index = (" );
            for( j = 0; j < cdims; j++ )
                ts->printf( CvTS::LOG, "%d%s", indices->data.i[i*cdims + j],
                                        j < cdims-1 ? ", " : ")\n" );
            break;
        }
    }

    if( code < 0 )
        ts->set_failed_test_info( code );
    return code;
}
Esempio n. 3
0
int CV_ThreshHistTest::validate_test_results( int /*test_case_idx*/ )
{
    int code = CvTS::OK;
    int i;
    float* ptr0 = values->data.fl;
    float* ptr = 0;
    CvSparseMat* sparse = 0;

    if( hist_type == CV_HIST_ARRAY )
        ptr = (float*)cvPtr1D( hist[0]->bins, 0 );
    else
        sparse = (CvSparseMat*)hist[0]->bins;

    if( code > 0 )
    {
        for( i = 0; i < orig_nz_count; i++ )
        {
            float v0 = ptr0[i], v;

            if( hist_type == CV_HIST_ARRAY )
                v = ptr[i];
            else
            {
                v = (float)cvGetRealND( sparse, indices->data.i + i*cdims );
                cvClearND( sparse, indices->data.i + i*cdims );
            }

            if( v0 <= threshold ) v0 = 0.f;
            if( cvIsNaN(v) || cvIsInf(v) )
            {
                ts->printf( CvTS::LOG, "The %d-th bin is invalid (=%g)\n", i, v );
                code = CvTS::FAIL_INVALID_OUTPUT;
                break;
            }
            else if( fabs(v0 - v) > FLT_EPSILON*10*fabs(v0) )
            {
                ts->printf( CvTS::LOG, "The %d-th bin is incorrect (=%g, should be =%g)\n", i, v, v0 );
                code = CvTS::FAIL_BAD_ACCURACY;
                break;
            }
        }
    }
    
    if( code > 0 && hist_type == CV_HIST_SPARSE )
    {
        if( sparse->heap->active_count > 0 )
        {
            ts->printf( CvTS::LOG,
                "There some extra histogram bins in the sparse histogram after the thresholding\n" );
            code = CvTS::FAIL_INVALID_OUTPUT;
        }
    }

    if( code < 0 )
        ts->set_failed_test_info( code );
    return code;
}
Esempio n. 4
0
int CV_MinMaxHistTest::validate_test_results( int /*test_case_idx*/ )
{
    int code = CvTS::OK;
    
    if( cvIsNaN(min_val) || cvIsInf(min_val) ||
        cvIsNaN(max_val) || cvIsInf(max_val) )
    {
        ts->printf( CvTS::LOG,
            "The extrema histogram bin values are invalid (min = %g, max = %g)\n", min_val, max_val );
        code = CvTS::FAIL_INVALID_OUTPUT;
    }
    else if( fabs(min_val - min_val0) > FLT_EPSILON ||
             fabs(max_val - max_val0) > FLT_EPSILON )
    {
        ts->printf( CvTS::LOG,
            "The extrema histogram bin values are incorrect: (min = %g, should be = %g), (max = %g, should be = %g)\n",
            min_val, min_val0, max_val, max_val0 );
        code = CvTS::FAIL_BAD_ACCURACY;
    }
    else
    {
        int i;
        for( i = 0; i < cdims; i++ )
        {
            if( min_idx[i] != min_idx0[i] || max_idx[i] != max_idx0[i] )
            {
                ts->printf( CvTS::LOG,
                    "The %d-th coordinates of extrema histogram bin values are incorrect: "
                    "(min = %d, should be = %d), (max = %d, should be = %d)\n",
                    i, min_idx[i], min_idx0[i], max_idx[i], max_idx0[i] );
                code = CvTS::FAIL_BAD_ACCURACY;
            }
        }
    }

    if( code < 0 )
        ts->set_failed_test_info( code );
    return code;
}
Esempio n. 5
0
/*
 * call-seq:
 *   angle -> float
 *
 * Return angle.
 */
VALUE
rb_angle(VALUE self)
{
  CvMoments *moments = CVMOMENTS(self);
  double
    m11 = cvGetCentralMoment(moments, 1, 1),
    m20 = cvGetCentralMoment(moments, 2, 0),
    m02 = cvGetCentralMoment(moments, 0, 2),
    mangle = 0.5 * atan(2 * m11 / (m20 - m02));
  if(cvIsNaN(mangle) || cvIsInf(mangle))
    return Qnil;
  else
    return rb_float_new(mangle);
}
Esempio n. 6
0
File: HDR.cpp Progetto: brunopop/hdr
	void Tonemap::computeLuminance(void)
	{
		luminanceMap = Image(height, width, CV_32F);
		// Take luminance of first pixel as min value
		minLum = 0.2126f * radianceMap.ptr<float>(0)[2] + 0.7152f * radianceMap.ptr<float>(0)[1] + 0.0722f * radianceMap.ptr<float>(0)[0];
		// Set all other values to zero
		maxLum = 0;
		avgLum = 0;
		logAvgLum = 0;
		int numNotNaNPx = 0;	// number of pixels that are not NaN
		int numLogPx = 0; // number of non-zero pixels

		// For all pixels
		for (int i=0; i<height; i++)
		{
			// Pointer to the ith row of the luminance map
			float* p = luminanceMap.ptr<float>(i);
			// Pointer to the ith row of the radiance map
			float* e = radianceMap.ptr<float>(i);
			for (int j=0; j<width; j++)
			{
				// Compute luminance value
				p[j] = 0.2126f * e[3*j + 2] + 0.7152f * e[3*j + 1] + 0.0722f * e[3*j + 0];
				// Compute min and max luminance values
				if (p[j] > maxLum) maxLum = p[j];
				if (p[j] < minLum) minLum = p[j];
				// Compute average luminance avoiding NaN values
				if (cvIsNaN(p[j]) == 0)
				{
					avgLum += long double(p[j]);
					numNotNaNPx++;
				}
				else
				{
#ifdef DEBUG
					std::cout << "Warning! Pixel location (" << i << "," << j << ") in radiance map is NaN."
							  << "\n\tRed channel value is " << e[3*j + 2]
							  << "\n\tGreen channel value is " << e[3*j + 1]
							  << "\n\tBlue channel value is " << e[3*j + 0]
							  << std::endl;
#endif
				}
				// Compute log average for non-zero pixels
				if (p[j] > 0)
				{
					logAvgLum += log(p[j]);
					numLogPx++;
				}
			}
Esempio n. 7
0
int CV_BayesianProbTest::validate_test_results( int /*test_case_idx*/ )
{
    int code = CvTS::OK;
    int i, j, n = hist_count/2;
    double s[CV_MAX_DIM];
    const double err_level = 1e-5;

    for( i = 0; i < total_size; i++ )
    {
        double sum = 0;
        for( j = 0; j < n; j++ )
        {
            double v = hist[j]->mat.data.fl[i];
            sum += v;
            s[j] = v;
        }
        sum = sum > DBL_EPSILON ? 1./sum : 0;

        for( j = 0; j < n; j++ )
        {
            double v0 = s[j]*sum;
            double v = hist[j+n]->mat.data.fl[i];

            if( cvIsNaN(v) || cvIsInf(v) )
            {
                ts->printf( CvTS::LOG,
                    "The element #%d in the destination histogram #%d is invalid (=%g)\n",
                    i, j, v );
                code = CvTS::FAIL_INVALID_OUTPUT;
                break;
            }
            else if( fabs(v0 - v) > err_level*fabs(v0) )
            {
                ts->printf( CvTS::LOG,
                    "The element #%d in the destination histogram #%d is inaccurate (=%g, should be =%g)\n",
                    i, j, v, v0 );
                code = CvTS::FAIL_BAD_ACCURACY;
                break;
            }
        }
        if( j < n )
            break;
    }

    if( code < 0 )
        ts->set_failed_test_info( code );
    return code;
}
Esempio n. 8
0
int CV_NormHistTest::validate_test_results( int /*test_case_idx*/ )
{
    int code = CvTS::OK;
    double sum = 0;
    
    if( hist_type == CV_HIST_ARRAY )
    {
        int i;
        const float* ptr = (float*)cvPtr1D( hist[0]->bins, 0 );

        for( i = 0; i < total_size; i++ )
            sum += ptr[i];
    }
    else
    {
        CvSparseMat* sparse = (CvSparseMat*)hist[0]->bins;
        CvSparseMatIterator iterator;
        CvSparseNode *node;
        
        for( node = cvInitSparseMatIterator( sparse, &iterator );
             node != 0; node = cvGetNextSparseNode( &iterator ))
        {
            sum += *(float*)CV_NODE_VAL(sparse,node);
        }
    }

    if( cvIsNaN(sum) || cvIsInf(sum) )
    {
        ts->printf( CvTS::LOG,
            "The normalized histogram has invalid sum =%g\n", sum );
        code = CvTS::FAIL_INVALID_OUTPUT;
    }
    else if( fabs(sum - factor) > FLT_EPSILON*10*fabs(factor) )
    {
        ts->printf( CvTS::LOG,
            "The normalized histogram has incorrect sum =%g, while it should be =%g\n", sum, factor );
        code = CvTS::FAIL_BAD_ACCURACY;
    }

    if( code < 0 )
        ts->set_failed_test_info( code );
    return code;
}
bool MotionTrackerFB::isFlowCorrect(cv::Point2f u)
{
    return !cvIsNaN(u.x) && !cvIsNaN(u.y) && fabs(u.x) < 1e9 && fabs(u.y) < 1e9;
}
Esempio n. 10
0
void CV_OptFlowPyrLKTest::run( int )
{
    int code = cvtest::TS::OK;

    const double success_error_level = 0.3;
    const int bad_points_max = 8;

    /* test parameters */
    double  max_err = 0., sum_err = 0;
    int     pt_cmpd = 0;
    int     pt_exceed = 0;
    int     merr_i = 0, merr_j = 0, merr_k = 0;
    char    filename[1000];

    CvPoint2D32f *u = 0, *v = 0, *v2 = 0;
    CvMat *_u = 0, *_v = 0, *_v2 = 0;
    char* status = 0;

    IplImage* imgI = 0;
    IplImage* imgJ = 0;

    int  n = 0, i = 0;

    sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "lk_prev.dat" );
    _u = (CvMat*)cvLoad( filename );

    if( !_u )
    {
        ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
        code = cvtest::TS::FAIL_MISSING_TEST_DATA;
        goto _exit_;
    }

    sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "lk_next.dat" );
    _v = (CvMat*)cvLoad( filename );

    if( !_v )
    {
        ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
        code = cvtest::TS::FAIL_MISSING_TEST_DATA;
        goto _exit_;
    }

    if( _u->cols != 2 || CV_MAT_TYPE(_u->type) != CV_32F ||
        _v->cols != 2 || CV_MAT_TYPE(_v->type) != CV_32F || _v->rows != _u->rows )
    {
        ts->printf( cvtest::TS::LOG, "the loaded matrices of points are not valid\n" );
        code = cvtest::TS::FAIL_MISSING_TEST_DATA;
        goto _exit_;

    }

    u = (CvPoint2D32f*)_u->data.fl;
    v = (CvPoint2D32f*)_v->data.fl;

    /* allocate adidtional buffers */
    _v2 = cvCloneMat( _u );
    v2 = (CvPoint2D32f*)_v2->data.fl;

    /* read first image */
    sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "rock_1.bmp" );
    imgI = cvLoadImage( filename, -1 );

    if( !imgI )
    {
        ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
        code = cvtest::TS::FAIL_MISSING_TEST_DATA;
        goto _exit_;
    }

    /* read second image */
    sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "rock_2.bmp" );
    imgJ = cvLoadImage( filename, -1 );

    if( !imgJ )
    {
        ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
        code = cvtest::TS::FAIL_MISSING_TEST_DATA;
        goto _exit_;
    }

    n = _u->rows;
    status = (char*)cvAlloc(n*sizeof(status[0]));

    /* calculate flow */
    cvCalcOpticalFlowPyrLK( imgI, imgJ, 0, 0, u, v2, n, cvSize( 41, 41 ),
                            4, status, 0, cvTermCriteria( CV_TERMCRIT_ITER|
                            CV_TERMCRIT_EPS, 30, 0.01f ), 0 );

    /* compare results */
    for( i = 0; i < n; i++ )
    {
        if( status[i] != 0 )
        {
            double err;
            if( cvIsNaN(v[i].x) )
            {
                merr_j++;
                continue;
            }

            err = fabs(v2[i].x - v[i].x) + fabs(v2[i].y - v[i].y);
            if( err > max_err )
            {
                max_err = err;
                merr_i = i;
            }

            pt_exceed += err > success_error_level;
            sum_err += err;
            pt_cmpd++;
        }
        else
        {
            if( !cvIsNaN( v[i].x ))
            {
                merr_i = i;
                merr_k++;
                ts->printf( cvtest::TS::LOG, "The algorithm lost the point #%d\n", i );
                code = cvtest::TS::FAIL_BAD_ACCURACY;
                goto _exit_;
            }
        }
    }

    if( pt_exceed > bad_points_max )
    {
        ts->printf( cvtest::TS::LOG,
                   "The number of poorly tracked points is too big (>=%d)\n", pt_exceed );
        code = cvtest::TS::FAIL_BAD_ACCURACY;
        goto _exit_;
    }

    if( max_err > 1 )
    {
        ts->printf( cvtest::TS::LOG, "Maximum tracking error is too big (=%g) at %d\n", max_err, merr_i );
        code = cvtest::TS::FAIL_BAD_ACCURACY;
        goto _exit_;
    }

_exit_:

    cvFree( &status );
    cvReleaseMat( &_u );
    cvReleaseMat( &_v );
    cvReleaseMat( &_v2 );

    cvReleaseImage( &imgI );
    cvReleaseImage( &imgJ );

    if( code < 0 )
        ts->set_failed_test_info( code );
}
Esempio n. 11
0
int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion )
{
    const float samePointEps = 0.00001; // used to test if two points are the same

    Point2f vec1[4], vec2[4];
    Point2f pts1[4], pts2[4];

    std::vector <Point2f> intersection;

    rect1.points(pts1);
    rect2.points(pts2);

    int ret = INTERSECT_FULL;

    // Specical case of rect1 == rect2
    {
        bool same = true;

        for( int i = 0; i < 4; i++ )
        {
            if( fabs(pts1[i].x - pts2[i].x) > samePointEps || (fabs(pts1[i].y - pts2[i].y) > samePointEps) )
            {
                same = false;
                break;
            }
        }

        if(same)
        {
            intersection.resize(4);

            for( int i = 0; i < 4; i++ )
            {
                intersection[i] = pts1[i];
            }

            Mat(intersection).copyTo(intersectingRegion);

            return INTERSECT_FULL;
        }
    }

    // Line vector
    // A line from p1 to p2 is: p1 + (p2-p1)*t, t=[0,1]
    for( int i = 0; i < 4; i++ )
    {
        vec1[i].x = pts1[(i+1)%4].x - pts1[i].x;
        vec1[i].y = pts1[(i+1)%4].y - pts1[i].y;

        vec2[i].x = pts2[(i+1)%4].x - pts2[i].x;
        vec2[i].y = pts2[(i+1)%4].y - pts2[i].y;
    }

    // Line test - test all line combos for intersection
    for( int i = 0; i < 4; i++ )
    {
        for( int j = 0; j < 4; j++ )
        {
            // Solve for 2x2 Ax=b
            float x21 = pts2[j].x - pts1[i].x;
            float y21 = pts2[j].y - pts1[i].y;

            float vx1 = vec1[i].x;
            float vy1 = vec1[i].y;

            float vx2 = vec2[j].x;
            float vy2 = vec2[j].y;

            float det = vx2*vy1 - vx1*vy2;

            float t1 = (vx2*y21 - vy2*x21) / det;
            float t2 = (vx1*y21 - vy1*x21) / det;

            // This takes care of parallel lines
            if( cvIsInf(t1) || cvIsInf(t2) || cvIsNaN(t1) || cvIsNaN(t2) )
            {
                continue;
            }

            if( t1 >= 0.0f && t1 <= 1.0f && t2 >= 0.0f && t2 <= 1.0f )
            {
                float xi = pts1[i].x + vec1[i].x*t1;
                float yi = pts1[i].y + vec1[i].y*t1;

                intersection.push_back(Point2f(xi,yi));
            }
        }
    }

    if( !intersection.empty() )
    {
        ret = INTERSECT_PARTIAL;
    }

    // Check for vertices from rect1 inside recct2
    for( int i = 0; i < 4; i++ )
    {
        // We do a sign test to see which side the point lies.
        // If the point all lie on the same sign for all 4 sides of the rect,
        // then there's an intersection
        int posSign = 0;
        int negSign = 0;

        float x = pts1[i].x;
        float y = pts1[i].y;

        for( int j = 0; j < 4; j++ )
        {
            // line equation: Ax + By + C = 0
            // see which side of the line this point is at
            float A = -vec2[j].y;
            float B = vec2[j].x;
            float C = -(A*pts2[j].x + B*pts2[j].y);

            float s = A*x+ B*y+ C;

            if( s >= 0 )
            {
                posSign++;
            }
            else
            {
                negSign++;
            }
        }

        if( posSign == 4 || negSign == 4 )
        {
            intersection.push_back(pts1[i]);
        }
    }

    // Reverse the check - check for vertices from rect2 inside recct1
    for( int i = 0; i < 4; i++ )
    {
        // We do a sign test to see which side the point lies.
        // If the point all lie on the same sign for all 4 sides of the rect,
        // then there's an intersection
        int posSign = 0;
        int negSign = 0;

        float x = pts2[i].x;
        float y = pts2[i].y;

        for( int j = 0; j < 4; j++ )
        {
            // line equation: Ax + By + C = 0
            // see which side of the line this point is at
            float A = -vec1[j].y;
            float B = vec1[j].x;
            float C = -(A*pts1[j].x + B*pts1[j].y);

            float s = A*x + B*y + C;

            if( s >= 0 )
            {
                posSign++;
            }
            else
            {
                negSign++;
            }
        }

        if( posSign == 4 || negSign == 4 )
        {
            intersection.push_back(pts2[i]);
        }
    }

    // Get rid of dupes
    for( int i = 0; i < (int)intersection.size()-1; i++ )
    {
        for( size_t j = i+1; j < intersection.size(); j++ )
        {
            float dx = intersection[i].x - intersection[j].x;
            float dy = intersection[i].y - intersection[j].y;
            double d2 = dx*dx + dy*dy; // can be a really small number, need double here

            if( d2 < samePointEps*samePointEps )
            {
                // Found a dupe, remove it
                std::swap(intersection[j], intersection.back());
                intersection.pop_back();
                i--; // restart check
            }
        }
    }

    if( intersection.empty() )
    {
        return INTERSECT_NONE ;
    }

    // If this check fails then it means we're getting dupes, increase samePointEps
    CV_Assert( intersection.size() <= 8 );

    Mat(intersection).copyTo(intersectingRegion);

    return ret;
}
Esempio n. 12
0
	inline bool isFlowCorrect(Point2f u)
	{
	    return !cvIsNaN(u.x) && !cvIsNaN(u.y) && fabs(u.x) < 1e9 && fabs(u.y) < 1e9;
	}
bool CameraInteraction::isFlowCorrect(float u) {
  return !cvIsNaN(u) && (fabs(u) < 1e9);
}
Esempio n. 14
0
 CV_EXPORTS
 inline bool
 isValidDepth(const double & depth)
 {
   return !cvIsNaN(depth);
 }
Esempio n. 15
0
 /** Checks if the value is a valid depth. For CV_16U or CV_16S, the convention is to be invalid if it is
  * a limit. For a float/double, we just check if it is a NaN
  * @param depth the depth to check for validity
  */
 CV_EXPORTS
 inline bool
 isValidDepth(const float & depth)
 {
   return !cvIsNaN(depth);
 }
Esempio n. 16
0
// source point clouds are assumed to contain their normals
int ICP::registerModelToScene(const Mat& srcPC, const Mat& dstPC, double& residual, Matx44d& pose)
{
  int n = srcPC.rows;

  const bool useRobustReject = m_rejectionScale>0;

  Mat srcTemp = srcPC.clone();
  Mat dstTemp = dstPC.clone();
  Vec3d meanSrc, meanDst;
  computeMeanCols(srcTemp, meanSrc);
  computeMeanCols(dstTemp, meanDst);
  Vec3d meanAvg = 0.5 * (meanSrc + meanDst);
  subtractColumns(srcTemp, meanAvg);
  subtractColumns(dstTemp, meanAvg);

  double distSrc = computeDistToOrigin(srcTemp);
  double distDst = computeDistToOrigin(dstTemp);

  double scale = (double)n / ((distSrc + distDst)*0.5);

  srcTemp(cv::Range(0, srcTemp.rows), cv::Range(0,3)) *= scale;
  dstTemp(cv::Range(0, dstTemp.rows), cv::Range(0,3)) *= scale;

  Mat srcPC0 = srcTemp;
  Mat dstPC0 = dstTemp;

  // initialize pose
  pose = Matx44d::eye();

  Mat M = Mat::eye(4,4,CV_64F);

  double tempResidual = 0;


  // walk the pyramid
  for (int level = m_numLevels-1; level >=0; level--)
  {
    const double impact = 2;
    double div = pow((double)impact, (double)level);
    //double div2 = div*div;
    const int numSamples = cvRound((double)(n/(div)));
    const double TolP = m_tolerance*(double)(level+1)*(level+1);
    const int MaxIterationsPyr = cvRound((double)m_maxIterations/(level+1));

    // Obtain the sampled point clouds for this level: Also rotates the normals
    Mat srcPCT = transformPCPose(srcPC0, pose);

    const int sampleStep = cvRound((double)n/(double)numSamples);

    srcPCT = samplePCUniform(srcPCT, sampleStep);
    /*
    Tolga Birdal thinks that downsampling the scene points might decrease the accuracy.
    Hamdi Sahloul, however, noticed that accuracy increased (pose residual decreased slightly).
    */
    Mat dstPCS = samplePCUniform(dstPC0, sampleStep);
    void* flann = indexPCFlann(dstPCS);

    double fval_old=9999999999;
    double fval_perc=0;
    double fval_min=9999999999;
    Mat Src_Moved = srcPCT.clone();

    int i=0;

    size_t numElSrc = (size_t)Src_Moved.rows;
    int sizesResult[2] = {(int)numElSrc, 1};
    float* distances = new float[numElSrc];
    int* indices = new int[numElSrc];

    Mat Indices(2, sizesResult, CV_32S, indices, 0);
    Mat Distances(2, sizesResult, CV_32F, distances, 0);

    // use robust weighting for outlier treatment
    int* indicesModel = new int[numElSrc];
    int* indicesScene = new int[numElSrc];

    int* newI = new int[numElSrc];
    int* newJ = new int[numElSrc];

    Matx44d PoseX = Matx44d::eye();

    while ( (!(fval_perc<(1+TolP) && fval_perc>(1-TolP))) && i<MaxIterationsPyr)
    {
      uint di=0, selInd = 0;

      queryPCFlann(flann, Src_Moved, Indices, Distances);

      for (di=0; di<numElSrc; di++)
      {
        newI[di] = di;
        newJ[di] = indices[di];
      }

      if (useRobustReject)
      {
        int numInliers = 0;
        float threshold = getRejectionThreshold(distances, Distances.rows, m_rejectionScale);
        Mat acceptInd = Distances<threshold;

        uchar *accPtr = (uchar*)acceptInd.data;
        for (int l=0; l<acceptInd.rows; l++)
        {
          if (accPtr[l])
          {
            newI[numInliers] = l;
            newJ[numInliers] = indices[l];
            numInliers++;
          }
        }
        numElSrc=numInliers;
      }

      // Step 2: Picky ICP
      // Among the resulting corresponding pairs, if more than one scene point p_i
      // is assigned to the same model point m_j, then select p_i that corresponds
      // to the minimum distance

      hashtable_int* duplicateTable = getHashtable(newJ, numElSrc, dstPCS.rows);

      for (di=0; di<duplicateTable->size; di++)
      {
        hashnode_i *node = duplicateTable->nodes[di];

        if (node)
        {
          // select the first node
          size_t idx = reinterpret_cast<size_t>(node->data)-1, dn=0;
          int dup = (int)node->key-1;
          size_t minIdxD = idx;
          float minDist = distances[idx];

          while ( node )
          {
            idx = reinterpret_cast<size_t>(node->data)-1;

            if (distances[idx] < minDist)
            {
              minDist = distances[idx];
              minIdxD = idx;
            }

            node = node->next;
            dn++;
          }

          indicesModel[ selInd ] = newI[ minIdxD ];
          indicesScene[ selInd ] = dup ;
          selInd++;
        }
      }

      hashtableDestroy(duplicateTable);

      if (selInd >= 6)
      {

        Mat Src_Match = Mat(selInd, srcPCT.cols, CV_64F);
        Mat Dst_Match = Mat(selInd, srcPCT.cols, CV_64F);

        for (di=0; di<selInd; di++)
        {
          const int indModel = indicesModel[di];
          const int indScene = indicesScene[di];
          const float *srcPt = srcPCT.ptr<float>(indModel);
          const float *dstPt = dstPCS.ptr<float>(indScene);
          double *srcMatchPt = Src_Match.ptr<double>(di);
          double *dstMatchPt = Dst_Match.ptr<double>(di);
          int ci=0;

          for (ci=0; ci<srcPCT.cols; ci++)
          {
            srcMatchPt[ci] = (double)srcPt[ci];
            dstMatchPt[ci] = (double)dstPt[ci];
          }
        }

        Vec3d rpy, t;
        minimizePointToPlaneMetric(Src_Match, Dst_Match, rpy, t);
        if (cvIsNaN(cv::trace(rpy)) || cvIsNaN(cv::norm(t)))
          break;
        getTransformMat(rpy, t, PoseX);
        Src_Moved = transformPCPose(srcPCT, PoseX);

        double fval = cv::norm(Src_Match, Dst_Match)/(double)(Src_Moved.rows);

        // Calculate change in error between iterations
        fval_perc=fval/fval_old;

        // Store error value
        fval_old=fval;

        if (fval < fval_min)
          fval_min = fval;
      }
      else
        break;

      i++;

    }

    pose = PoseX * pose;
    residual = tempResidual;

    delete[] newI;
    delete[] newJ;
    delete[] indicesModel;
    delete[] indicesScene;
    delete[] distances;
    delete[] indices;

    tempResidual = fval_min;
    destroyFlann(flann);
  }

  Matx33d Rpose;
  Vec3d Cpose;
  poseToRT(pose, Rpose, Cpose);
  Cpose = Cpose / scale + meanAvg - Rpose * meanAvg;
  rtToPose(Rpose, Cpose, pose);

  residual = tempResidual;

  return 0;
}
bool cv::find4QuadCornerSubpix(InputArray _img, InputOutputArray _corners, Size region_size)
{
    CV_INSTRUMENT_REGION();

    Mat img = _img.getMat(), cornersM = _corners.getMat();
    int ncorners = cornersM.checkVector(2, CV_32F);
    CV_Assert( ncorners >= 0 );
    Point2f* corners = cornersM.ptr<Point2f>();
    const int nbins = 256;
    float ranges[] = {0, 256};
    const float* _ranges = ranges;
    Mat hist;

    Mat black_comp, white_comp;
    for(int i = 0; i < ncorners; i++)
    {
        int channels = 0;
        Rect roi(cvRound(corners[i].x - region_size.width), cvRound(corners[i].y - region_size.height),
            region_size.width*2 + 1, region_size.height*2 + 1);
        Mat img_roi = img(roi);
        calcHist(&img_roi, 1, &channels, Mat(), hist, 1, &nbins, &_ranges);

        int black_thresh = 0, white_thresh = 0;
        segment_hist_max(hist, black_thresh, white_thresh);

        threshold(img, black_comp, black_thresh, 255.0, THRESH_BINARY_INV);
        threshold(img, white_comp, white_thresh, 255.0, THRESH_BINARY);

        const int erode_count = 1;
        erode(black_comp, black_comp, Mat(), Point(-1, -1), erode_count);
        erode(white_comp, white_comp, Mat(), Point(-1, -1), erode_count);

        std::vector<std::vector<Point> > white_contours, black_contours;
        findContours(black_comp, black_contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
        findContours(white_comp, white_contours, RETR_LIST, CHAIN_APPROX_SIMPLE);

        if(black_contours.size() < 5 || white_contours.size() < 5) continue;

        // find two white and black blobs that are close to the input point
        std::vector<std::pair<int, float> > white_order, black_order;
        orderContours(black_contours, corners[i], black_order);
        orderContours(white_contours, corners[i], white_order);

        const float max_dist = 10.0f;
        if(black_order[0].second > max_dist || black_order[1].second > max_dist ||
           white_order[0].second > max_dist || white_order[1].second > max_dist)
        {
            continue; // there will be no improvement in this corner position
        }

        const std::vector<Point>* quads[4] = {&black_contours[black_order[0].first], &black_contours[black_order[1].first],
                                         &white_contours[white_order[0].first], &white_contours[white_order[1].first]};
        std::vector<Point2f> quads_approx[4];
        Point2f quad_corners[4];
        for(int k = 0; k < 4; k++)
        {
            std::vector<Point2f> temp;
            for(size_t j = 0; j < quads[k]->size(); j++) temp.push_back((*quads[k])[j]);
            approxPolyDP(Mat(temp), quads_approx[k], 0.5, true);

            findCorner(quads_approx[k], corners[i], quad_corners[k]);
            quad_corners[k] += Point2f(0.5f, 0.5f);
        }

        // cross two lines
        Point2f origin1 = quad_corners[0];
        Point2f dir1 = quad_corners[1] - quad_corners[0];
        Point2f origin2 = quad_corners[2];
        Point2f dir2 = quad_corners[3] - quad_corners[2];
        double angle = acos(dir1.dot(dir2)/(norm(dir1)*norm(dir2)));
        if(cvIsNaN(angle) || cvIsInf(angle) || angle < 0.5 || angle > CV_PI - 0.5) continue;

        findLinesCrossPoint(origin1, dir1, origin2, dir2, corners[i]);
    }

    return true;
}
Esempio n. 18
0
int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )
{
    int code = CvTS::OK;
    int i;
    double result0[MAX_METHOD+1];
    double s0 = 0, s1 = 0, sq0 = 0, sq1 = 0, t;

    for( i = 0; i < MAX_METHOD; i++ )
        result0[i] = 0;

    if( hist_type == CV_HIST_ARRAY )
    {
        float* ptr0 = (float*)cvPtr1D( hist[0]->bins, 0 );
        float* ptr1 = (float*)cvPtr1D( hist[1]->bins, 0 );
        
        for( i = 0; i < total_size; i++ )
        {
            double v0 = ptr0[i], v1 = ptr1[i];
            result0[CV_COMP_CORREL] += v0*v1;
            result0[CV_COMP_INTERSECT] += MIN(v0,v1);
            if( fabs(v0 + v1) > DBL_EPSILON )
                result0[CV_COMP_CHISQR] += (v0 - v1)*(v0 - v1)/(v0 + v1);
            s0 += v0;
            s1 += v1;
            sq0 += v0*v0;
            sq1 += v1*v1;
            result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);
        }
    }
    else
    {
        CvSparseMat* sparse0 = (CvSparseMat*)hist[0]->bins;
        CvSparseMat* sparse1 = (CvSparseMat*)hist[1]->bins;
        CvSparseMatIterator iterator;
        CvSparseNode* node;

        for( node = cvInitSparseMatIterator( sparse0, &iterator );
             node != 0; node = cvGetNextSparseNode( &iterator ) )
        {
            const int* idx = CV_NODE_IDX(sparse0, node);
            double v0 = *(float*)CV_NODE_VAL(sparse0, node);
            double v1 = (float)cvGetRealND(sparse1, idx);

            result0[CV_COMP_CORREL] += v0*v1;
            result0[CV_COMP_INTERSECT] += MIN(v0,v1);
            if( fabs(v0 + v1) > DBL_EPSILON )
                result0[CV_COMP_CHISQR] += (v0 - v1)*(v0 - v1)/(v0 + v1);
            s0 += v0;
            sq0 += v0*v0;
            result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);
        }

        for( node = cvInitSparseMatIterator( sparse1, &iterator );
             node != 0; node = cvGetNextSparseNode( &iterator ) )
        {
            const int* idx = CV_NODE_IDX(sparse1, node);
            double v1 = *(float*)CV_NODE_VAL(sparse1, node);
            double v0 = (float)cvGetRealND(sparse0, idx);

            if( fabs(v0) < DBL_EPSILON )
                result0[CV_COMP_CHISQR] += v1;
            s1 += v1;
            sq1 += v1*v1;
        }
    }

    t = (sq0 - s0*s0/total_size)*(sq1 - s1*s1/total_size);
    result0[CV_COMP_CORREL] = fabs(t) > DBL_EPSILON ?
        (result0[CV_COMP_CORREL] - s0*s1/total_size)/sqrt(t) : 1;

    s1 *= s0;
    s0 = result0[CV_COMP_BHATTACHARYYA];
    s0 = 1. - s0*(s1 > FLT_EPSILON ? 1./sqrt(s1) : 1.);
    result0[CV_COMP_BHATTACHARYYA] = sqrt(MAX(s0,0.));

    for( i = 0; i < MAX_METHOD; i++ )
    {
        double v = result[i], v0 = result0[i];
        const char* method_name =
            i == CV_COMP_CHISQR ? "Chi-Square" :
            i == CV_COMP_CORREL ? "Correlation" :
            i == CV_COMP_INTERSECT ? "Intersection" :
            i == CV_COMP_BHATTACHARYYA ? "Bhattacharyya" : "Unknown";

        if( cvIsNaN(v) || cvIsInf(v) )
        {
            ts->printf( CvTS::LOG, "The comparison result using the method #%d (%s) is invalid (=%g)\n",
                i, method_name, v );
            code = CvTS::FAIL_INVALID_OUTPUT;
            break;
        }
        else if( fabs(v0 - v) > FLT_EPSILON*10*MAX(fabs(v0),0.1) )
        {
            ts->printf( CvTS::LOG, "The comparison result using the method #%d (%s)\n\tis inaccurate (=%g, should be =%g)\n",
                i, method_name, v, v0 );
            code = CvTS::FAIL_BAD_ACCURACY;
            break;
        }
    }

    if( code < 0 )
        ts->set_failed_test_info( code );
    return code;
}