Merge pull request #482 from vpisarev:c2cpp_imgproc_part2
This commit is contained in:
commit
4cc3dfe27c
@ -1969,6 +1969,11 @@ static TransposeInplaceFunc transposeInplaceTab[] =
|
||||
void cv::transpose( InputArray _src, OutputArray _dst )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
if( src.empty() )
|
||||
{
|
||||
_dst.release();
|
||||
return;
|
||||
}
|
||||
size_t esz = src.elemSize();
|
||||
CV_Assert( src.dims <= 2 && esz <= (size_t)32 );
|
||||
|
||||
|
@ -36,5 +36,6 @@ PERF_TEST_P(Image_RhoStep_ThetaStep_Threshold, HoughLines,
|
||||
|
||||
TEST_CYCLE() HoughLines(image, lines, rhoStep, thetaStep, threshold);
|
||||
|
||||
transpose(lines, lines);
|
||||
SANITY_CHECK(lines);
|
||||
}
|
||||
|
@ -1,374 +0,0 @@
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 _CV_LIST_H_
|
||||
#define _CV_LIST_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define CV_FORCE_INLINE CV_INLINE
|
||||
|
||||
#if !defined(_LIST_INLINE)
|
||||
#define _LIST_INLINE CV_FORCE_INLINE
|
||||
#endif /*_LIST_INLINE*/
|
||||
|
||||
#if defined DECLARE_LIST
|
||||
#if defined _MSC_VER && _MSC_VER >= 1200
|
||||
#pragma warning("DECLARE_LIST macro is already defined!")
|
||||
#endif
|
||||
#endif /*DECLARE_LIST*/
|
||||
|
||||
static const long default_size = 10;
|
||||
static const long default_inc_size = 10;
|
||||
|
||||
struct _pos
|
||||
{
|
||||
void* m_pos;
|
||||
#ifdef _DEBUG
|
||||
struct _list* m_list;
|
||||
#endif /*_DEBUG*/
|
||||
};
|
||||
typedef struct _pos CVPOS;
|
||||
struct _list
|
||||
{
|
||||
void* m_buffer;
|
||||
void* m_first_buffer;
|
||||
long m_buf_size; /* The size of the buffer */
|
||||
long m_size; /* The number of elements */
|
||||
CVPOS m_head;
|
||||
CVPOS m_tail;
|
||||
CVPOS m_head_free;
|
||||
};
|
||||
|
||||
typedef struct _list _CVLIST;
|
||||
|
||||
#define DECLARE_LIST(type, prefix)\
|
||||
/* Basic element of a list*/\
|
||||
struct prefix##element_##type\
|
||||
{\
|
||||
struct prefix##element_##type* m_prev;\
|
||||
struct prefix##element_##type* m_next;\
|
||||
type m_data;\
|
||||
};\
|
||||
typedef struct prefix##element_##type ELEMENT_##type;\
|
||||
/* Initialization and destruction*/\
|
||||
_LIST_INLINE _CVLIST* prefix##create_list_##type(long);\
|
||||
_LIST_INLINE void prefix##destroy_list_##type(_CVLIST*);\
|
||||
/* Access functions*/\
|
||||
_LIST_INLINE CVPOS prefix##get_head_pos_##type(_CVLIST*);\
|
||||
_LIST_INLINE CVPOS prefix##get_tail_pos_##type(_CVLIST*);\
|
||||
_LIST_INLINE type* prefix##get_next_##type(CVPOS*);\
|
||||
_LIST_INLINE type* prefix##get_prev_##type(CVPOS*);\
|
||||
_LIST_INLINE int prefix##is_pos_##type(CVPOS pos);\
|
||||
/* Modification functions*/\
|
||||
_LIST_INLINE void prefix##clear_list_##type(_CVLIST*);\
|
||||
_LIST_INLINE CVPOS prefix##add_head_##type(_CVLIST*, type*);\
|
||||
_LIST_INLINE CVPOS prefix##add_tail_##type(_CVLIST*, type*);\
|
||||
_LIST_INLINE void prefix##remove_head_##type(_CVLIST*);\
|
||||
_LIST_INLINE void prefix##remove_tail_##type(_CVLIST*);\
|
||||
_LIST_INLINE CVPOS prefix##insert_before_##type(_CVLIST*, CVPOS, type*);\
|
||||
_LIST_INLINE CVPOS prefix##insert_after_##type(_CVLIST*, CVPOS, type*);\
|
||||
_LIST_INLINE void prefix##remove_at_##type(_CVLIST*, CVPOS);\
|
||||
_LIST_INLINE void prefix##set_##type(CVPOS, type*);\
|
||||
_LIST_INLINE type* prefix##get_##type(CVPOS);\
|
||||
/* Statistics functions*/\
|
||||
_LIST_INLINE int prefix##get_count_##type(_CVLIST*);
|
||||
|
||||
/* This macro finds a space for a new element and puts in into 'element' pointer */
|
||||
#define INSERT_NEW(element_type, l, element)\
|
||||
l->m_size++;\
|
||||
if(l->m_head_free.m_pos != NULL)\
|
||||
{\
|
||||
element = (element_type*)(l->m_head_free.m_pos);\
|
||||
if(element->m_next != NULL)\
|
||||
{\
|
||||
element->m_next->m_prev = NULL;\
|
||||
l->m_head_free.m_pos = element->m_next;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
l->m_head_free.m_pos = NULL;\
|
||||
}\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
if(l->m_buf_size < l->m_size && l->m_head_free.m_pos == NULL)\
|
||||
{\
|
||||
*(void**)l->m_buffer = cvAlloc(l->m_buf_size*sizeof(element_type) + sizeof(void*));\
|
||||
l->m_buffer = *(void**)l->m_buffer;\
|
||||
*(void**)l->m_buffer = NULL;\
|
||||
element = (element_type*)((char*)l->m_buffer + sizeof(void*));\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
element = (element_type*)((char*)l->m_buffer + sizeof(void*)) + l->m_size - 1;\
|
||||
}\
|
||||
}
|
||||
|
||||
/* This macro adds 'element' to the list of free elements*/
|
||||
#define INSERT_FREE(element_type, l, element)\
|
||||
if(l->m_head_free.m_pos != NULL)\
|
||||
{\
|
||||
((element_type*)l->m_head_free.m_pos)->m_prev = element;\
|
||||
}\
|
||||
element->m_next = ((element_type*)l->m_head_free.m_pos);\
|
||||
l->m_head_free.m_pos = element;
|
||||
|
||||
|
||||
/*#define GET_FIRST_FREE(l) ((ELEMENT_##type*)(l->m_head_free.m_pos))*/
|
||||
|
||||
#define IMPLEMENT_LIST(type, prefix)\
|
||||
_CVLIST* prefix##create_list_##type(long size)\
|
||||
{\
|
||||
_CVLIST* pl = (_CVLIST*)cvAlloc(sizeof(_CVLIST));\
|
||||
pl->m_buf_size = size > 0 ? size : default_size;\
|
||||
pl->m_first_buffer = cvAlloc(pl->m_buf_size*sizeof(ELEMENT_##type) + sizeof(void*));\
|
||||
pl->m_buffer = pl->m_first_buffer;\
|
||||
*(void**)pl->m_buffer = NULL;\
|
||||
pl->m_size = 0;\
|
||||
pl->m_head.m_pos = NULL;\
|
||||
pl->m_tail.m_pos = NULL;\
|
||||
pl->m_head_free.m_pos = NULL;\
|
||||
return pl;\
|
||||
}\
|
||||
void prefix##destroy_list_##type(_CVLIST* l)\
|
||||
{\
|
||||
void* cur = l->m_first_buffer;\
|
||||
void* next;\
|
||||
while(cur)\
|
||||
{\
|
||||
next = *(void**)cur;\
|
||||
cvFree(&cur);\
|
||||
cur = next;\
|
||||
}\
|
||||
cvFree(&l);\
|
||||
}\
|
||||
CVPOS prefix##get_head_pos_##type(_CVLIST* l)\
|
||||
{\
|
||||
return l->m_head;\
|
||||
}\
|
||||
CVPOS prefix##get_tail_pos_##type(_CVLIST* l)\
|
||||
{\
|
||||
return l->m_tail;\
|
||||
}\
|
||||
type* prefix##get_next_##type(CVPOS* pos)\
|
||||
{\
|
||||
if(pos->m_pos)\
|
||||
{\
|
||||
ELEMENT_##type* element = (ELEMENT_##type*)(pos->m_pos);\
|
||||
pos->m_pos = element->m_next;\
|
||||
return &element->m_data;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
return NULL;\
|
||||
}\
|
||||
}\
|
||||
type* prefix##get_prev_##type(CVPOS* pos)\
|
||||
{\
|
||||
if(pos->m_pos)\
|
||||
{\
|
||||
ELEMENT_##type* element = (ELEMENT_##type*)(pos->m_pos);\
|
||||
pos->m_pos = element->m_prev;\
|
||||
return &element->m_data;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
return NULL;\
|
||||
}\
|
||||
}\
|
||||
int prefix##is_pos_##type(CVPOS pos)\
|
||||
{\
|
||||
return !!pos.m_pos;\
|
||||
}\
|
||||
void prefix##clear_list_##type(_CVLIST* l)\
|
||||
{\
|
||||
l->m_head.m_pos = NULL;\
|
||||
l->m_tail.m_pos = NULL;\
|
||||
l->m_size = 0;\
|
||||
l->m_head_free.m_pos = NULL;\
|
||||
}\
|
||||
CVPOS prefix##add_head_##type(_CVLIST* l, type* data)\
|
||||
{\
|
||||
ELEMENT_##type* element;\
|
||||
INSERT_NEW(ELEMENT_##type, l, element);\
|
||||
element->m_prev = NULL;\
|
||||
element->m_next = (ELEMENT_##type*)(l->m_head.m_pos);\
|
||||
memcpy(&(element->m_data), data, sizeof(*data));\
|
||||
if(element->m_next)\
|
||||
{\
|
||||
element->m_next->m_prev = element;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
l->m_tail.m_pos = element;\
|
||||
}\
|
||||
l->m_head.m_pos = element;\
|
||||
return l->m_head;\
|
||||
}\
|
||||
CVPOS prefix##add_tail_##type(_CVLIST* l, type* data)\
|
||||
{\
|
||||
ELEMENT_##type* element;\
|
||||
INSERT_NEW(ELEMENT_##type, l, element);\
|
||||
element->m_next = NULL;\
|
||||
element->m_prev = (ELEMENT_##type*)(l->m_tail.m_pos);\
|
||||
memcpy(&(element->m_data), data, sizeof(*data));\
|
||||
if(element->m_prev)\
|
||||
{\
|
||||
element->m_prev->m_next = element;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
l->m_head.m_pos = element;\
|
||||
}\
|
||||
l->m_tail.m_pos = element;\
|
||||
return l->m_tail;\
|
||||
}\
|
||||
void prefix##remove_head_##type(_CVLIST* l)\
|
||||
{\
|
||||
ELEMENT_##type* element = ((ELEMENT_##type*)(l->m_head.m_pos));\
|
||||
if(element->m_next != NULL)\
|
||||
{\
|
||||
element->m_next->m_prev = NULL;\
|
||||
}\
|
||||
l->m_head.m_pos = element->m_next;\
|
||||
INSERT_FREE(ELEMENT_##type, l, element);\
|
||||
l->m_size--;\
|
||||
}\
|
||||
void prefix##remove_tail_##type(_CVLIST* l)\
|
||||
{\
|
||||
ELEMENT_##type* element = ((ELEMENT_##type*)(l->m_tail.m_pos));\
|
||||
if(element->m_prev != NULL)\
|
||||
{\
|
||||
element->m_prev->m_next = NULL;\
|
||||
}\
|
||||
l->m_tail.m_pos = element->m_prev;\
|
||||
INSERT_FREE(ELEMENT_##type, l, element);\
|
||||
l->m_size--;\
|
||||
}\
|
||||
CVPOS prefix##insert_after_##type(_CVLIST* l, CVPOS pos, type* data)\
|
||||
{\
|
||||
ELEMENT_##type* element;\
|
||||
ELEMENT_##type* before;\
|
||||
CVPOS newpos;\
|
||||
INSERT_NEW(ELEMENT_##type, l, element);\
|
||||
memcpy(&(element->m_data), data, sizeof(*data));\
|
||||
before = (ELEMENT_##type*)pos.m_pos;\
|
||||
element->m_prev = before;\
|
||||
element->m_next = before->m_next;\
|
||||
before->m_next = element;\
|
||||
if(element->m_next != NULL)\
|
||||
element->m_next->m_prev = element;\
|
||||
else\
|
||||
l->m_tail.m_pos = element;\
|
||||
newpos.m_pos = element;\
|
||||
return newpos;\
|
||||
}\
|
||||
CVPOS prefix##insert_before_##type(_CVLIST* l, CVPOS pos, type* data)\
|
||||
{\
|
||||
ELEMENT_##type* element;\
|
||||
ELEMENT_##type* after;\
|
||||
CVPOS newpos;\
|
||||
INSERT_NEW(ELEMENT_##type, l, element);\
|
||||
memcpy(&(element->m_data), data, sizeof(*data));\
|
||||
after = (ELEMENT_##type*)pos.m_pos;\
|
||||
element->m_prev = after->m_prev;\
|
||||
element->m_next = after;\
|
||||
after->m_prev = element;\
|
||||
if(element->m_prev != NULL)\
|
||||
element->m_prev->m_next = element;\
|
||||
else\
|
||||
l->m_head.m_pos = element;\
|
||||
newpos.m_pos = element;\
|
||||
return newpos;\
|
||||
}\
|
||||
void prefix##remove_at_##type(_CVLIST* l, CVPOS pos)\
|
||||
{\
|
||||
ELEMENT_##type* element = ((ELEMENT_##type*)pos.m_pos);\
|
||||
if(element->m_prev != NULL)\
|
||||
{\
|
||||
element->m_prev->m_next = element->m_next;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
l->m_head.m_pos = element->m_next;\
|
||||
}\
|
||||
if(element->m_next != NULL)\
|
||||
{\
|
||||
element->m_next->m_prev = element->m_prev;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
l->m_tail.m_pos = element->m_prev;\
|
||||
}\
|
||||
INSERT_FREE(ELEMENT_##type, l, element);\
|
||||
l->m_size--;\
|
||||
}\
|
||||
void prefix##set_##type(CVPOS pos, type* data)\
|
||||
{\
|
||||
ELEMENT_##type* element = ((ELEMENT_##type*)(pos.m_pos));\
|
||||
memcpy(&(element->m_data), data, sizeof(*data));\
|
||||
}\
|
||||
type* prefix##get_##type(CVPOS pos)\
|
||||
{\
|
||||
ELEMENT_##type* element = ((ELEMENT_##type*)(pos.m_pos));\
|
||||
return &(element->m_data);\
|
||||
}\
|
||||
int prefix##get_count_##type(_CVLIST* list)\
|
||||
{\
|
||||
return list->m_size;\
|
||||
}
|
||||
|
||||
#define DECLARE_AND_IMPLEMENT_LIST(type, prefix)\
|
||||
DECLARE_LIST(type, prefix)\
|
||||
IMPLEMENT_LIST(type, prefix)
|
||||
|
||||
typedef struct __index
|
||||
{
|
||||
int value;
|
||||
float rho, theta;
|
||||
}
|
||||
_index;
|
||||
|
||||
DECLARE_LIST( _index, h_ )
|
||||
|
||||
#endif/*_CV_LIST_H_*/
|
@ -7,10 +7,11 @@
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -23,7 +24,7 @@
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// * 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
|
||||
@ -40,119 +41,43 @@
|
||||
//M*/
|
||||
#include "precomp.hpp"
|
||||
|
||||
CV_IMPL void
|
||||
cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* corners,
|
||||
int count, CvSize win, CvSize zeroZone,
|
||||
CvTermCriteria criteria )
|
||||
void cv::cornerSubPix( InputArray _image, InputOutputArray _corners,
|
||||
Size win, Size zeroZone, TermCriteria criteria )
|
||||
{
|
||||
cv::AutoBuffer<float> buffer;
|
||||
|
||||
const int MAX_ITERS = 100;
|
||||
const float drv[] = { -1.f, 0.f, 1.f };
|
||||
float *maskX;
|
||||
float *maskY;
|
||||
float *mask;
|
||||
float *src_buffer;
|
||||
float *gx_buffer;
|
||||
float *gy_buffer;
|
||||
int win_w = win.width * 2 + 1, win_h = win.height * 2 + 1;
|
||||
int win_rect_size = (win_w + 4) * (win_h + 4);
|
||||
double coeff;
|
||||
CvSize size, src_buf_size;
|
||||
int i, j, k, pt_i;
|
||||
int max_iters = 10;
|
||||
double eps = 0;
|
||||
int i, j, k;
|
||||
int max_iters = (criteria.type & CV_TERMCRIT_ITER) ? MIN(MAX(criteria.maxCount, 1), MAX_ITERS) : MAX_ITERS;
|
||||
double eps = (criteria.type & CV_TERMCRIT_EPS) ? MAX(criteria.epsilon, 0.) : 0;
|
||||
eps *= eps; // use square of error in comparsion operations
|
||||
|
||||
CvMat stub, *src = (CvMat*)srcarr;
|
||||
src = cvGetMat( srcarr, &stub );
|
||||
|
||||
if( CV_MAT_TYPE( src->type ) != CV_8UC1 )
|
||||
CV_Error( CV_StsUnsupportedFormat, "The source image must be 8-bit single-channel (CV_8UC1)" );
|
||||
|
||||
if( !corners )
|
||||
CV_Error( CV_StsNullPtr, "" );
|
||||
|
||||
if( count < 0 )
|
||||
CV_Error( CV_StsBadSize, "" );
|
||||
cv::Mat src = _image.getMat(), cornersmat = _corners.getMat();
|
||||
int count = cornersmat.checkVector(2, CV_32F);
|
||||
CV_Assert( count >= 0 );
|
||||
Point2f* corners = (Point2f*)cornersmat.data;
|
||||
|
||||
if( count == 0 )
|
||||
return;
|
||||
|
||||
if( win.width <= 0 || win.height <= 0 )
|
||||
CV_Error( CV_StsBadSize, "" );
|
||||
CV_Assert( win.width > 0 && win.height > 0 );
|
||||
CV_Assert( src.cols >= win.width*2 + 5 && src.rows >= win.height*2 + 5 );
|
||||
CV_Assert( src.channels() == 1 );
|
||||
|
||||
size = cvGetMatSize( src );
|
||||
|
||||
if( size.width < win_w + 4 || size.height < win_h + 4 )
|
||||
CV_Error( CV_StsBadSize, "" );
|
||||
|
||||
/* initialize variables, controlling loop termination */
|
||||
switch( criteria.type )
|
||||
{
|
||||
case CV_TERMCRIT_ITER:
|
||||
eps = 0.f;
|
||||
max_iters = criteria.max_iter;
|
||||
break;
|
||||
case CV_TERMCRIT_EPS:
|
||||
eps = criteria.epsilon;
|
||||
max_iters = MAX_ITERS;
|
||||
break;
|
||||
case CV_TERMCRIT_ITER | CV_TERMCRIT_EPS:
|
||||
eps = criteria.epsilon;
|
||||
max_iters = criteria.max_iter;
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
CV_Error( CV_StsBadFlag, "" );
|
||||
}
|
||||
|
||||
eps = MAX( eps, 0 );
|
||||
eps *= eps; /* use square of error in comparsion operations. */
|
||||
|
||||
max_iters = MAX( max_iters, 1 );
|
||||
max_iters = MIN( max_iters, MAX_ITERS );
|
||||
|
||||
buffer.allocate( win_rect_size * 5 + win_w + win_h + 32 );
|
||||
|
||||
/* assign pointers */
|
||||
maskX = buffer;
|
||||
maskY = maskX + win_w + 4;
|
||||
mask = maskY + win_h + 4;
|
||||
src_buffer = mask + win_w * win_h;
|
||||
gx_buffer = src_buffer + win_rect_size;
|
||||
gy_buffer = gx_buffer + win_rect_size;
|
||||
|
||||
coeff = 1. / (win.width * win.width);
|
||||
|
||||
/* calculate mask */
|
||||
for( i = -win.width, k = 0; i <= win.width; i++, k++ )
|
||||
{
|
||||
maskX[k] = (float)exp( -i * i * coeff );
|
||||
}
|
||||
|
||||
if( win.width == win.height )
|
||||
{
|
||||
maskY = maskX;
|
||||
}
|
||||
else
|
||||
{
|
||||
coeff = 1. / (win.height * win.height);
|
||||
for( i = -win.height, k = 0; i <= win.height; i++, k++ )
|
||||
{
|
||||
maskY[k] = (float) exp( -i * i * coeff );
|
||||
}
|
||||
}
|
||||
Mat maskm(win_h, win_w, CV_32F), subpix_buf(win_h+2, win_w+2, CV_32F);
|
||||
float* mask = maskm.ptr<float>();
|
||||
|
||||
for( i = 0; i < win_h; i++ )
|
||||
{
|
||||
float y = (float)(i - win.height)/win.height;
|
||||
float vy = std::exp(-y*y);
|
||||
for( j = 0; j < win_w; j++ )
|
||||
{
|
||||
mask[i * win_w + j] = maskX[j] * maskY[i];
|
||||
float x = (float)(j - win.width)/win.width;
|
||||
mask[i * win_w + j] = (float)(vy*std::exp(-x*x));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* make zero_zone */
|
||||
// make zero_zone
|
||||
if( zeroZone.width >= 0 && zeroZone.height >= 0 &&
|
||||
zeroZone.width * 2 + 1 < win_w && zeroZone.height * 2 + 1 < win_h )
|
||||
{
|
||||
@ -165,46 +90,31 @@ cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* corners,
|
||||
}
|
||||
}
|
||||
|
||||
/* set sizes of image rectangles, used in convolutions */
|
||||
src_buf_size.width = win_w + 2;
|
||||
src_buf_size.height = win_h + 2;
|
||||
|
||||
/* do optimization loop for all the points */
|
||||
for( pt_i = 0; pt_i < count; pt_i++ )
|
||||
// do optimization loop for all the points
|
||||
for( int pt_i = 0; pt_i < count; pt_i++ )
|
||||
{
|
||||
CvPoint2D32f cT = corners[pt_i], cI = cT;
|
||||
Point2f cT = corners[pt_i], cI = cT;
|
||||
int iter = 0;
|
||||
double err;
|
||||
double err = 0;
|
||||
|
||||
do
|
||||
{
|
||||
CvPoint2D32f cI2;
|
||||
double a, b, c, bb1, bb2;
|
||||
Point2f cI2;
|
||||
double a = 0, b = 0, c = 0, bb1 = 0, bb2 = 0;
|
||||
|
||||
IPPI_CALL( icvGetRectSubPix_8u32f_C1R( (uchar*)src->data.ptr, src->step, size,
|
||||
src_buffer, (win_w + 2) * sizeof( src_buffer[0] ),
|
||||
cvSize( win_w + 2, win_h + 2 ), cI ));
|
||||
getRectSubPix(src, Size(win_w+2, win_h+2), cI, subpix_buf, subpix_buf.type());
|
||||
const float* subpix = &subpix_buf.at<float>(1,1);
|
||||
|
||||
/* calc derivatives */
|
||||
icvSepConvSmall3_32f( src_buffer+src_buf_size.width, src_buf_size.width * sizeof(src_buffer[0]),
|
||||
gx_buffer, win_w * sizeof(gx_buffer[0]),
|
||||
src_buf_size, drv, NULL, NULL );
|
||||
icvSepConvSmall3_32f( src_buffer+1, src_buf_size.width * sizeof(src_buffer[0]),
|
||||
gy_buffer, win_w * sizeof(gy_buffer[0]),
|
||||
src_buf_size, NULL, drv, NULL );
|
||||
|
||||
a = b = c = bb1 = bb2 = 0;
|
||||
|
||||
/* process gradient */
|
||||
for( i = 0, k = 0; i < win_h; i++ )
|
||||
// process gradient
|
||||
for( i = 0, k = 0; i < win_h; i++, subpix += win_w + 2 )
|
||||
{
|
||||
double py = i - win.height;
|
||||
|
||||
for( j = 0; j < win_w; j++, k++ )
|
||||
{
|
||||
double m = mask[k];
|
||||
double tgx = gx_buffer[k];
|
||||
double tgy = gy_buffer[k];
|
||||
double tgx = subpix[j+1] - subpix[j-1];
|
||||
double tgy = subpix[j+win_w+2] - subpix[j-win_w-2];
|
||||
double gxx = tgx * tgx * m;
|
||||
double gxy = tgx * tgy * m;
|
||||
double gyy = tgy * tgy * m;
|
||||
@ -220,46 +130,40 @@ cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* corners,
|
||||
}
|
||||
|
||||
double det=a*c-b*b;
|
||||
if( fabs( det ) > DBL_EPSILON*DBL_EPSILON )
|
||||
{
|
||||
// 2x2 matrix inversion
|
||||
double scale=1.0/det;
|
||||
cI2.x = (float)(cI.x + c*scale*bb1 - b*scale*bb2);
|
||||
cI2.y = (float)(cI.y - b*scale*bb1 + a*scale*bb2);
|
||||
}
|
||||
else
|
||||
{
|
||||
cI2 = cI;
|
||||
}
|
||||
if( fabs( det ) <= DBL_EPSILON*DBL_EPSILON )
|
||||
break;
|
||||
|
||||
// 2x2 matrix inversion
|
||||
double scale=1.0/det;
|
||||
cI2.x = (float)(cI.x + c*scale*bb1 - b*scale*bb2);
|
||||
cI2.y = (float)(cI.y - b*scale*bb1 + a*scale*bb2);
|
||||
err = (cI2.x - cI.x) * (cI2.x - cI.x) + (cI2.y - cI.y) * (cI2.y - cI.y);
|
||||
cI = cI2;
|
||||
if( cI.x < 0 || cI.x >= src.cols || cI.y < 0 || cI.y >= src.rows )
|
||||
break;
|
||||
}
|
||||
while( ++iter < max_iters && err > eps );
|
||||
|
||||
/* if new point is too far from initial, it means poor convergence.
|
||||
leave initial point as the result */
|
||||
// if new point is too far from initial, it means poor convergence.
|
||||
// leave initial point as the result
|
||||
if( fabs( cI.x - cT.x ) > win.width || fabs( cI.y - cT.y ) > win.height )
|
||||
{
|
||||
cI = cT;
|
||||
}
|
||||
|
||||
corners[pt_i] = cI; /* store result */
|
||||
corners[pt_i] = cI;
|
||||
}
|
||||
}
|
||||
|
||||
void cv::cornerSubPix( InputArray _image, InputOutputArray _corners,
|
||||
Size winSize, Size zeroZone,
|
||||
TermCriteria criteria )
|
||||
{
|
||||
Mat corners = _corners.getMat();
|
||||
int ncorners = corners.checkVector(2);
|
||||
CV_Assert( ncorners >= 0 && corners.depth() == CV_32F );
|
||||
Mat image = _image.getMat();
|
||||
CvMat c_image = image;
|
||||
|
||||
cvFindCornerSubPix( &c_image, (CvPoint2D32f*)corners.data, ncorners,
|
||||
winSize, zeroZone, criteria );
|
||||
CV_IMPL void
|
||||
cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* _corners,
|
||||
int count, CvSize win, CvSize zeroZone,
|
||||
CvTermCriteria criteria )
|
||||
{
|
||||
if(!_corners || count <= 0)
|
||||
return;
|
||||
|
||||
cv::Mat src = cv::cvarrToMat(srcarr), corners(count, 1, CV_32FC2, _corners);
|
||||
cv::cornerSubPix(src, corners, win, zeroZone, criteria);
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
|
@ -43,83 +43,6 @@
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
static IppStatus sts = ippInit();
|
||||
#endif
|
||||
/****************************************************************************************/
|
||||
|
||||
/* lightweight convolution with 3x3 kernel */
|
||||
void icvSepConvSmall3_32f( float* src, int src_step, float* dst, int dst_step,
|
||||
CvSize src_size, const float* kx, const float* ky, float* buffer )
|
||||
{
|
||||
int dst_width, buffer_step = 0;
|
||||
int x, y;
|
||||
bool fast_kx = true, fast_ky = true;
|
||||
|
||||
assert( src && dst && src_size.width > 2 && src_size.height > 2 &&
|
||||
(src_step & 3) == 0 && (dst_step & 3) == 0 &&
|
||||
(kx || ky) && (buffer || !kx || !ky));
|
||||
|
||||
src_step /= sizeof(src[0]);
|
||||
dst_step /= sizeof(dst[0]);
|
||||
|
||||
dst_width = src_size.width - 2;
|
||||
|
||||
if( !kx )
|
||||
{
|
||||
/* set vars, so that vertical convolution
|
||||
will write results into destination ROI and
|
||||
horizontal convolution won't run */
|
||||
src_size.width = dst_width;
|
||||
buffer_step = dst_step;
|
||||
buffer = dst;
|
||||
dst_width = 0;
|
||||
}
|
||||
else
|
||||
fast_kx = kx[1] == 0.f && kx[0] == -kx[2] && kx[0] == -1.f;
|
||||
|
||||
assert( src_step >= src_size.width && dst_step >= dst_width );
|
||||
|
||||
src_size.height -= 2;
|
||||
if( !ky )
|
||||
{
|
||||
/* set vars, so that vertical convolution won't run and
|
||||
horizontal convolution will write results into destination ROI */
|
||||
src_size.height += 2;
|
||||
buffer_step = src_step;
|
||||
buffer = src;
|
||||
src_size.width = 0;
|
||||
}
|
||||
else
|
||||
fast_ky = ky[1] == 0.f && ky[0] == -ky[2] && ky[0] == -1.f;
|
||||
|
||||
for( y = 0; y < src_size.height; y++, src += src_step,
|
||||
dst += dst_step,
|
||||
buffer += buffer_step )
|
||||
{
|
||||
float* src2 = src + src_step;
|
||||
float* src3 = src + src_step*2;
|
||||
if( fast_ky )
|
||||
for( x = 0; x < src_size.width; x++ )
|
||||
{
|
||||
buffer[x] = (float)(src3[x] - src[x]);
|
||||
}
|
||||
else
|
||||
for( x = 0; x < src_size.width; x++ )
|
||||
{
|
||||
buffer[x] = (float)(ky[0]*src[x] + ky[1]*src2[x] + ky[2]*src3[x]);
|
||||
}
|
||||
|
||||
if( fast_kx )
|
||||
for( x = 0; x < dst_width; x++ )
|
||||
{
|
||||
dst[x] = (float)(buffer[x+2] - buffer[x]);
|
||||
}
|
||||
else
|
||||
for( x = 0; x < dst_width; x++ )
|
||||
{
|
||||
dst[x] = (float)(kx[0]*buffer[x] + kx[1]*buffer[x+1] + kx[2]*buffer[x+2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
Sobel & Scharr Derivative Filters
|
||||
|
@ -7,10 +7,11 @@
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -23,7 +24,7 @@
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// * 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
|
||||
@ -40,44 +41,48 @@
|
||||
//M*/
|
||||
#include "precomp.hpp"
|
||||
|
||||
#define ICV_DIST_SHIFT 16
|
||||
#define ICV_INIT_DIST0 (INT_MAX >> 2)
|
||||
|
||||
static CvStatus
|
||||
icvInitTopBottom( int* temp, int tempstep, CvSize size, int border )
|
||||
namespace cv
|
||||
{
|
||||
int i, j;
|
||||
for( i = 0; i < border; i++ )
|
||||
{
|
||||
int* ttop = (int*)(temp + i*tempstep);
|
||||
int* tbottom = (int*)(temp + (size.height + border*2 - i - 1)*tempstep);
|
||||
|
||||
for( j = 0; j < size.width + border*2; j++ )
|
||||
static const int DIST_SHIFT = 16;
|
||||
static const int INIT_DIST0 = (INT_MAX >> 2);
|
||||
|
||||
static void
|
||||
initTopBottom( Mat& temp, int border )
|
||||
{
|
||||
Size size = temp.size();
|
||||
for( int i = 0; i < border; i++ )
|
||||
{
|
||||
int* ttop = temp.ptr<int>(i);
|
||||
int* tbottom = temp.ptr<int>(size.height - i - 1);
|
||||
|
||||
for( int j = 0; j < size.width; j++ )
|
||||
{
|
||||
ttop[j] = ICV_INIT_DIST0;
|
||||
tbottom[j] = ICV_INIT_DIST0;
|
||||
ttop[j] = INIT_DIST0;
|
||||
tbottom[j] = INIT_DIST0;
|
||||
}
|
||||
}
|
||||
|
||||
return CV_OK;
|
||||
}
|
||||
|
||||
|
||||
static CvStatus CV_STDCALL
|
||||
icvDistanceTransform_3x3_C1R( const uchar* src, int srcstep, int* temp,
|
||||
int step, float* dist, int dststep, CvSize size, const float* metrics )
|
||||
static void
|
||||
distanceTransform_3x3( const Mat& _src, Mat& _temp, Mat& _dist, const float* metrics )
|
||||
{
|
||||
const int BORDER = 1;
|
||||
int i, j;
|
||||
const int HV_DIST = CV_FLT_TO_FIX( metrics[0], ICV_DIST_SHIFT );
|
||||
const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], ICV_DIST_SHIFT );
|
||||
const float scale = 1.f/(1 << ICV_DIST_SHIFT);
|
||||
const int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT );
|
||||
const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT );
|
||||
const float scale = 1.f/(1 << DIST_SHIFT);
|
||||
|
||||
srcstep /= sizeof(src[0]);
|
||||
step /= sizeof(temp[0]);
|
||||
dststep /= sizeof(dist[0]);
|
||||
const uchar* src = _src.data;
|
||||
int* temp = _temp.ptr<int>();
|
||||
float* dist = _dist.ptr<float>();
|
||||
int srcstep = (int)(_src.step/sizeof(src[0]));
|
||||
int step = (int)(_temp.step/sizeof(temp[0]));
|
||||
int dststep = (int)(_dist.step/sizeof(dist[0]));
|
||||
Size size = _src.size();
|
||||
|
||||
icvInitTopBottom( temp, step, size, BORDER );
|
||||
initTopBottom( _temp, BORDER );
|
||||
|
||||
// forward pass
|
||||
for( i = 0; i < size.height; i++ )
|
||||
@ -86,7 +91,7 @@ icvDistanceTransform_3x3_C1R( const uchar* src, int srcstep, int* temp,
|
||||
int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
|
||||
for( j = 0; j < BORDER; j++ )
|
||||
tmp[-j-1] = tmp[size.width + j] = ICV_INIT_DIST0;
|
||||
tmp[-j-1] = tmp[size.width + j] = INIT_DIST0;
|
||||
|
||||
for( j = 0; j < size.width; j++ )
|
||||
{
|
||||
@ -130,27 +135,28 @@ icvDistanceTransform_3x3_C1R( const uchar* src, int srcstep, int* temp,
|
||||
d[j] = (float)(t0 * scale);
|
||||
}
|
||||
}
|
||||
|
||||
return CV_OK;
|
||||
}
|
||||
|
||||
|
||||
static CvStatus CV_STDCALL
|
||||
icvDistanceTransform_5x5_C1R( const uchar* src, int srcstep, int* temp,
|
||||
int step, float* dist, int dststep, CvSize size, const float* metrics )
|
||||
static void
|
||||
distanceTransform_5x5( const Mat& _src, Mat& _temp, Mat& _dist, const float* metrics )
|
||||
{
|
||||
const int BORDER = 2;
|
||||
int i, j;
|
||||
const int HV_DIST = CV_FLT_TO_FIX( metrics[0], ICV_DIST_SHIFT );
|
||||
const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], ICV_DIST_SHIFT );
|
||||
const int LONG_DIST = CV_FLT_TO_FIX( metrics[2], ICV_DIST_SHIFT );
|
||||
const float scale = 1.f/(1 << ICV_DIST_SHIFT);
|
||||
const int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT );
|
||||
const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT );
|
||||
const int LONG_DIST = CV_FLT_TO_FIX( metrics[2], DIST_SHIFT );
|
||||
const float scale = 1.f/(1 << DIST_SHIFT);
|
||||
|
||||
srcstep /= sizeof(src[0]);
|
||||
step /= sizeof(temp[0]);
|
||||
dststep /= sizeof(dist[0]);
|
||||
const uchar* src = _src.data;
|
||||
int* temp = _temp.ptr<int>();
|
||||
float* dist = _dist.ptr<float>();
|
||||
int srcstep = (int)(_src.step/sizeof(src[0]));
|
||||
int step = (int)(_temp.step/sizeof(temp[0]));
|
||||
int dststep = (int)(_dist.step/sizeof(dist[0]));
|
||||
Size size = _src.size();
|
||||
|
||||
icvInitTopBottom( temp, step, size, BORDER );
|
||||
initTopBottom( _temp, BORDER );
|
||||
|
||||
// forward pass
|
||||
for( i = 0; i < size.height; i++ )
|
||||
@ -159,7 +165,7 @@ icvDistanceTransform_5x5_C1R( const uchar* src, int srcstep, int* temp,
|
||||
int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
|
||||
for( j = 0; j < BORDER; j++ )
|
||||
tmp[-j-1] = tmp[size.width + j] = ICV_INIT_DIST0;
|
||||
tmp[-j-1] = tmp[size.width + j] = INIT_DIST0;
|
||||
|
||||
for( j = 0; j < size.width; j++ )
|
||||
{
|
||||
@ -219,30 +225,31 @@ icvDistanceTransform_5x5_C1R( const uchar* src, int srcstep, int* temp,
|
||||
d[j] = (float)(t0 * scale);
|
||||
}
|
||||
}
|
||||
|
||||
return CV_OK;
|
||||
}
|
||||
|
||||
|
||||
static CvStatus CV_STDCALL
|
||||
icvDistanceTransformEx_5x5_C1R( const uchar* src, int srcstep, int* temp,
|
||||
int step, float* dist, int dststep, int* labels, int lstep,
|
||||
CvSize size, const float* metrics )
|
||||
static void
|
||||
distanceTransformEx_5x5( const Mat& _src, Mat& _temp, Mat& _dist, Mat& _labels, const float* metrics )
|
||||
{
|
||||
const int BORDER = 2;
|
||||
|
||||
int i, j;
|
||||
const int HV_DIST = CV_FLT_TO_FIX( metrics[0], ICV_DIST_SHIFT );
|
||||
const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], ICV_DIST_SHIFT );
|
||||
const int LONG_DIST = CV_FLT_TO_FIX( metrics[2], ICV_DIST_SHIFT );
|
||||
const float scale = 1.f/(1 << ICV_DIST_SHIFT);
|
||||
const int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT );
|
||||
const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT );
|
||||
const int LONG_DIST = CV_FLT_TO_FIX( metrics[2], DIST_SHIFT );
|
||||
const float scale = 1.f/(1 << DIST_SHIFT);
|
||||
|
||||
srcstep /= sizeof(src[0]);
|
||||
step /= sizeof(temp[0]);
|
||||
dststep /= sizeof(dist[0]);
|
||||
lstep /= sizeof(labels[0]);
|
||||
const uchar* src = _src.data;
|
||||
int* temp = _temp.ptr<int>();
|
||||
float* dist = _dist.ptr<float>();
|
||||
int* labels = _labels.ptr<int>();
|
||||
int srcstep = (int)(_src.step/sizeof(src[0]));
|
||||
int step = (int)(_temp.step/sizeof(temp[0]));
|
||||
int dststep = (int)(_dist.step/sizeof(dist[0]));
|
||||
int lstep = (int)(_labels.step/sizeof(dist[0]));
|
||||
Size size = _src.size();
|
||||
|
||||
icvInitTopBottom( temp, step, size, BORDER );
|
||||
initTopBottom( _temp, BORDER );
|
||||
|
||||
// forward pass
|
||||
for( i = 0; i < size.height; i++ )
|
||||
@ -252,7 +259,7 @@ icvDistanceTransformEx_5x5_C1R( const uchar* src, int srcstep, int* temp,
|
||||
int* lls = (int*)(labels + i*lstep);
|
||||
|
||||
for( j = 0; j < BORDER; j++ )
|
||||
tmp[-j-1] = tmp[size.width + j] = ICV_INIT_DIST0;
|
||||
tmp[-j-1] = tmp[size.width + j] = INIT_DIST0;
|
||||
|
||||
for( j = 0; j < size.width; j++ )
|
||||
{
|
||||
@ -263,7 +270,7 @@ icvDistanceTransformEx_5x5_C1R( const uchar* src, int srcstep, int* temp,
|
||||
}
|
||||
else
|
||||
{
|
||||
int t0 = ICV_INIT_DIST0, t;
|
||||
int t0 = INIT_DIST0, t;
|
||||
int l0 = 0;
|
||||
|
||||
t = tmp[j-step*2-1] + LONG_DIST;
|
||||
@ -388,16 +395,12 @@ icvDistanceTransformEx_5x5_C1R( const uchar* src, int srcstep, int* temp,
|
||||
d[j] = (float)(t0 * scale);
|
||||
}
|
||||
}
|
||||
|
||||
return CV_OK;
|
||||
}
|
||||
|
||||
|
||||
static CvStatus
|
||||
icvGetDistanceTransformMask( int maskType, float *metrics )
|
||||
static void getDistanceTransformMask( int maskType, float *metrics )
|
||||
{
|
||||
if( !metrics )
|
||||
return CV_NULLPTR_ERR;
|
||||
CV_Assert( metrics != 0 );
|
||||
|
||||
switch (maskType)
|
||||
{
|
||||
@ -434,18 +437,13 @@ icvGetDistanceTransformMask( int maskType, float *metrics )
|
||||
metrics[2] = 2.1969f;
|
||||
break;
|
||||
default:
|
||||
return CV_BADRANGE_ERR;
|
||||
CV_Error(CV_StsBadArg, "Uknown metric type");
|
||||
}
|
||||
|
||||
return CV_OK;
|
||||
}
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
struct DTColumnInvoker
|
||||
{
|
||||
DTColumnInvoker( const CvMat* _src, CvMat* _dst, const int* _sat_tab, const float* _sqr_tab)
|
||||
DTColumnInvoker( const Mat* _src, Mat* _dst, const int* _sat_tab, const float* _sqr_tab)
|
||||
{
|
||||
src = _src;
|
||||
dst = _dst;
|
||||
@ -463,8 +461,8 @@ struct DTColumnInvoker
|
||||
|
||||
for( i = i1; i < i2; i++ )
|
||||
{
|
||||
const uchar* sptr = src->data.ptr + i + (m-1)*sstep;
|
||||
float* dptr = dst->data.fl + i;
|
||||
const uchar* sptr = src->ptr(m-1) + i;
|
||||
float* dptr = dst->ptr<float>() + i;
|
||||
int j, dist = m-1;
|
||||
|
||||
for( j = m-1; j >= 0; j--, sptr -= sstep )
|
||||
@ -483,8 +481,8 @@ struct DTColumnInvoker
|
||||
}
|
||||
}
|
||||
|
||||
const CvMat* src;
|
||||
CvMat* dst;
|
||||
const Mat* src;
|
||||
Mat* dst;
|
||||
const int* sat_tab;
|
||||
const float* sqr_tab;
|
||||
};
|
||||
@ -492,7 +490,7 @@ struct DTColumnInvoker
|
||||
|
||||
struct DTRowInvoker
|
||||
{
|
||||
DTRowInvoker( CvMat* _dst, const float* _sqr_tab, const float* _inv_tab )
|
||||
DTRowInvoker( Mat* _dst, const float* _sqr_tab, const float* _inv_tab )
|
||||
{
|
||||
dst = _dst;
|
||||
sqr_tab = _sqr_tab;
|
||||
@ -511,7 +509,7 @@ struct DTRowInvoker
|
||||
|
||||
for( i = i1; i < i2; i++ )
|
||||
{
|
||||
float* d = (float*)(dst->data.ptr + i*dst->step);
|
||||
float* d = dst->ptr<float>(i);
|
||||
int p, q, k;
|
||||
|
||||
v[0] = 0;
|
||||
@ -549,27 +547,20 @@ struct DTRowInvoker
|
||||
}
|
||||
}
|
||||
|
||||
CvMat* dst;
|
||||
Mat* dst;
|
||||
const float* sqr_tab;
|
||||
const float* inv_tab;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
icvTrueDistTrans( const CvMat* src, CvMat* dst )
|
||||
trueDistTrans( const Mat& src, Mat& dst )
|
||||
{
|
||||
const float inf = 1e15f;
|
||||
|
||||
if( !CV_ARE_SIZES_EQ( src, dst ))
|
||||
CV_Error( CV_StsUnmatchedSizes, "" );
|
||||
CV_Assert( src.size() == dst.size() );
|
||||
|
||||
if( CV_MAT_TYPE(src->type) != CV_8UC1 ||
|
||||
CV_MAT_TYPE(dst->type) != CV_32FC1 )
|
||||
CV_Error( CV_StsUnsupportedFormat,
|
||||
"The input image must have 8uC1 type and the output one must have 32fC1 type" );
|
||||
|
||||
int i, m = src->rows, n = src->cols;
|
||||
CV_Assert( src.type() == CV_8UC1 && dst.type() == CV_32FC1 );
|
||||
int i, m = src.rows, n = src.cols;
|
||||
|
||||
cv::AutoBuffer<uchar> _buf(std::max(m*2*sizeof(float) + (m*3+1)*sizeof(int), n*2*sizeof(float)));
|
||||
// stage 1: compute 1d distance transform of each column
|
||||
@ -586,7 +577,7 @@ icvTrueDistTrans( const CvMat* src, CvMat* dst )
|
||||
for( ; i <= m*3; i++ )
|
||||
sat_tab[i] = i - shift;
|
||||
|
||||
cv::parallel_for(cv::BlockedRange(0, n), cv::DTColumnInvoker(src, dst, sat_tab, sqr_tab));
|
||||
cv::parallel_for(cv::BlockedRange(0, n), cv::DTColumnInvoker(&src, &dst, sat_tab, sqr_tab));
|
||||
|
||||
// stage 2: compute modified distance transform for each row
|
||||
float* inv_tab = sqr_tab + n;
|
||||
@ -598,50 +589,33 @@ icvTrueDistTrans( const CvMat* src, CvMat* dst )
|
||||
sqr_tab[i] = (float)(i*i);
|
||||
}
|
||||
|
||||
cv::parallel_for(cv::BlockedRange(0, m), cv::DTRowInvoker(dst, sqr_tab, inv_tab));
|
||||
cv::parallel_for(cv::BlockedRange(0, m), cv::DTRowInvoker(&dst, sqr_tab, inv_tab));
|
||||
}
|
||||
|
||||
|
||||
/*********************************** IPP functions *********************************/
|
||||
|
||||
typedef CvStatus (CV_STDCALL * CvIPPDistTransFunc)( const uchar* src, int srcstep,
|
||||
void* dst, int dststep,
|
||||
CvSize size, const void* metrics );
|
||||
|
||||
typedef CvStatus (CV_STDCALL * CvIPPDistTransFunc2)( uchar* src, int srcstep,
|
||||
CvSize size, const int* metrics );
|
||||
|
||||
/***********************************************************************************/
|
||||
|
||||
typedef CvStatus (CV_STDCALL * CvDistTransFunc)( const uchar* src, int srcstep,
|
||||
int* temp, int tempstep,
|
||||
float* dst, int dststep,
|
||||
CvSize size, const float* metrics );
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
Non-inplace and Inplace 8u->8u Distance Transform for CityBlock (a.k.a. L1) metric
|
||||
(C) 2006 by Jay Stavinzky.
|
||||
\****************************************************************************************/
|
||||
|
||||
//BEGIN ATS ADDITION
|
||||
/* 8-bit grayscale distance transform function */
|
||||
// 8-bit grayscale distance transform function
|
||||
static void
|
||||
icvDistanceATS_L1_8u( const CvMat* src, CvMat* dst )
|
||||
distanceATS_L1_8u( const Mat& src, Mat& dst )
|
||||
{
|
||||
int width = src->cols, height = src->rows;
|
||||
int width = src.cols, height = src.rows;
|
||||
|
||||
int a;
|
||||
uchar lut[256];
|
||||
int x, y;
|
||||
|
||||
const uchar *sbase = src->data.ptr;
|
||||
uchar *dbase = dst->data.ptr;
|
||||
int srcstep = src->step;
|
||||
int dststep = dst->step;
|
||||
const uchar *sbase = src.data;
|
||||
uchar *dbase = dst.data;
|
||||
int srcstep = (int)src.step;
|
||||
int dststep = (int)dst.step;
|
||||
|
||||
CV_Assert( CV_IS_MASK_ARR( src ) && CV_MAT_TYPE( dst->type ) == CV_8UC1 );
|
||||
CV_Assert( CV_ARE_SIZES_EQ( src, dst ));
|
||||
CV_Assert( src.type() == CV_8UC1 && dst.type() == CV_8UC1 );
|
||||
CV_Assert( src.size() == dst.size() );
|
||||
|
||||
////////////////////// forward scan ////////////////////////
|
||||
for( x = 0; x < 256; x++ )
|
||||
@ -689,7 +663,7 @@ icvDistanceATS_L1_8u( const CvMat* src, CvMat* dst )
|
||||
// do right edge
|
||||
a = lut[dbase[width-1+dststep]];
|
||||
dbase[width-1] = (uchar)(MIN(a, dbase[width-1]));
|
||||
|
||||
|
||||
for( x = width - 2; x >= 0; x-- )
|
||||
{
|
||||
int b = dbase[x+dststep];
|
||||
@ -700,150 +674,118 @@ icvDistanceATS_L1_8u( const CvMat* src, CvMat* dst )
|
||||
}
|
||||
//END ATS ADDITION
|
||||
|
||||
}
|
||||
|
||||
/* Wrapper function for distance transform group */
|
||||
CV_IMPL void
|
||||
cvDistTransform( const void* srcarr, void* dstarr,
|
||||
int distType, int maskSize,
|
||||
const float *mask,
|
||||
void* labelsarr, int labelType )
|
||||
|
||||
// Wrapper function for distance transform group
|
||||
void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labels,
|
||||
int distType, int maskSize, int labelType )
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat(), labels;
|
||||
bool need_labels = _labels.needed();
|
||||
|
||||
CV_Assert( src.type() == CV_8U );
|
||||
if( dst.size == src.size && dst.type() == CV_8U && !need_labels && distType == CV_DIST_L1 )
|
||||
{
|
||||
distanceATS_L1_8u(src, dst);
|
||||
return;
|
||||
}
|
||||
|
||||
_dst.create( src.size(), CV_32F );
|
||||
dst = _dst.getMat();
|
||||
|
||||
if( need_labels )
|
||||
{
|
||||
CV_Assert( labelType == DIST_LABEL_PIXEL || labelType == DIST_LABEL_CCOMP );
|
||||
|
||||
_labels.create(src.size(), CV_32S);
|
||||
labels = _labels.getMat();
|
||||
maskSize = CV_DIST_MASK_5;
|
||||
}
|
||||
|
||||
CV_Assert( src.type() == CV_8UC1 );
|
||||
float _mask[5] = {0};
|
||||
CvMat srcstub, *src = (CvMat*)srcarr;
|
||||
CvMat dststub, *dst = (CvMat*)dstarr;
|
||||
CvMat lstub, *labels = (CvMat*)labelsarr;
|
||||
|
||||
src = cvGetMat( src, &srcstub );
|
||||
dst = cvGetMat( dst, &dststub );
|
||||
|
||||
if( !CV_IS_MASK_ARR( src ) || (CV_MAT_TYPE( dst->type ) != CV_32FC1 &&
|
||||
(CV_MAT_TYPE(dst->type) != CV_8UC1 || distType != CV_DIST_L1 || labels)) )
|
||||
CV_Error( CV_StsUnsupportedFormat,
|
||||
"source image must be 8uC1 and the distance map must be 32fC1 "
|
||||
"(or 8uC1 in case of simple L1 distance transform)" );
|
||||
|
||||
if( !CV_ARE_SIZES_EQ( src, dst ))
|
||||
CV_Error( CV_StsUnmatchedSizes, "the source and the destination images must be of the same size" );
|
||||
|
||||
if( maskSize != CV_DIST_MASK_3 && maskSize != CV_DIST_MASK_5 && maskSize != CV_DIST_MASK_PRECISE )
|
||||
CV_Error( CV_StsBadSize, "Mask size should be 3 or 5 or 0 (presize)" );
|
||||
|
||||
if( distType == CV_DIST_C || distType == CV_DIST_L1 )
|
||||
maskSize = !labels ? CV_DIST_MASK_3 : CV_DIST_MASK_5;
|
||||
else if( distType == CV_DIST_L2 && labels )
|
||||
maskSize = !need_labels ? CV_DIST_MASK_3 : CV_DIST_MASK_5;
|
||||
else if( distType == CV_DIST_L2 && need_labels )
|
||||
maskSize = CV_DIST_MASK_5;
|
||||
|
||||
if( maskSize == CV_DIST_MASK_PRECISE )
|
||||
{
|
||||
icvTrueDistTrans( src, dst );
|
||||
trueDistTrans( src, dst );
|
||||
return;
|
||||
}
|
||||
|
||||
if( labels )
|
||||
CV_Assert( distType == CV_DIST_C || distType == CV_DIST_L1 || distType == CV_DIST_L2 );
|
||||
|
||||
getDistanceTransformMask( (distType == CV_DIST_C ? 0 :
|
||||
distType == CV_DIST_L1 ? 1 : 2) + maskSize*10, _mask );
|
||||
|
||||
Size size = src.size();
|
||||
|
||||
int border = maskSize == CV_DIST_MASK_3 ? 1 : 2;
|
||||
Mat temp( size.height + border*2, size.width + border*2, CV_32SC1 );
|
||||
|
||||
if( !need_labels )
|
||||
{
|
||||
labels = cvGetMat( labels, &lstub );
|
||||
if( CV_MAT_TYPE( labels->type ) != CV_32SC1 )
|
||||
CV_Error( CV_StsUnsupportedFormat, "the output array of labels must be 32sC1" );
|
||||
|
||||
if( !CV_ARE_SIZES_EQ( labels, dst ))
|
||||
CV_Error( CV_StsUnmatchedSizes, "the array of labels has a different size" );
|
||||
|
||||
if( maskSize == CV_DIST_MASK_3 )
|
||||
CV_Error( CV_StsNotImplemented,
|
||||
"3x3 mask can not be used for \"labeled\" distance transform. Use 5x5 mask" );
|
||||
}
|
||||
|
||||
if( distType == CV_DIST_C || distType == CV_DIST_L1 || distType == CV_DIST_L2 )
|
||||
{
|
||||
icvGetDistanceTransformMask( (distType == CV_DIST_C ? 0 :
|
||||
distType == CV_DIST_L1 ? 1 : 2) + maskSize*10, _mask );
|
||||
}
|
||||
else if( distType == CV_DIST_USER )
|
||||
{
|
||||
if( !mask )
|
||||
CV_Error( CV_StsNullPtr, "" );
|
||||
|
||||
memcpy( _mask, mask, (maskSize/2 + 1)*sizeof(float));
|
||||
}
|
||||
|
||||
CvSize size = cvGetMatSize(src);
|
||||
|
||||
if( CV_MAT_TYPE(dst->type) == CV_8UC1 )
|
||||
{
|
||||
icvDistanceATS_L1_8u( src, dst );
|
||||
distanceTransform_3x3(src, temp, dst, _mask);
|
||||
else
|
||||
distanceTransform_5x5(src, temp, dst, _mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
int border = maskSize == CV_DIST_MASK_3 ? 1 : 2;
|
||||
cv::Ptr<CvMat> temp = cvCreateMat( size.height + border*2, size.width + border*2, CV_32SC1 );
|
||||
labels.setTo(Scalar::all(0));
|
||||
|
||||
if( !labels )
|
||||
if( labelType == CV_DIST_LABEL_CCOMP )
|
||||
{
|
||||
CvDistTransFunc func = maskSize == CV_DIST_MASK_3 ?
|
||||
icvDistanceTransform_3x3_C1R :
|
||||
icvDistanceTransform_5x5_C1R;
|
||||
|
||||
func( src->data.ptr, src->step, temp->data.i, temp->step,
|
||||
dst->data.fl, dst->step, size, _mask );
|
||||
Mat zpix = src == 0;
|
||||
connectedComponents(zpix, labels, 8, CV_32S);
|
||||
}
|
||||
else
|
||||
{
|
||||
cvZero( labels );
|
||||
|
||||
if( labelType == CV_DIST_LABEL_CCOMP )
|
||||
int k = 1;
|
||||
for( int i = 0; i < src.rows; i++ )
|
||||
{
|
||||
CvSeq *contours = 0;
|
||||
cv::Ptr<CvMemStorage> st = cvCreateMemStorage();
|
||||
cv::Ptr<CvMat> src_copy = cvCreateMat( size.height+border*2, size.width+border*2, src->type );
|
||||
cvCopyMakeBorder(src, src_copy, cvPoint(border, border), IPL_BORDER_CONSTANT, cvScalarAll(255));
|
||||
cvCmpS( src_copy, 0, src_copy, CV_CMP_EQ );
|
||||
cvFindContours( src_copy, st, &contours, sizeof(CvContour),
|
||||
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(-border, -border));
|
||||
const uchar* srcptr = src.ptr(i);
|
||||
int* labelptr = labels.ptr<int>(i);
|
||||
|
||||
for( int label = 1; contours != 0; contours = contours->h_next, label++ )
|
||||
{
|
||||
CvScalar area_color = cvScalarAll(label);
|
||||
cvDrawContours( labels, contours, area_color, area_color, -255, -1, 8 );
|
||||
}
|
||||
for( int j = 0; j < src.cols; j++ )
|
||||
if( srcptr[j] == 0 )
|
||||
labelptr[j] = k++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int k = 1;
|
||||
for( int i = 0; i < src->rows; i++ )
|
||||
{
|
||||
const uchar* srcptr = src->data.ptr + src->step*i;
|
||||
int* labelptr = (int*)(labels->data.ptr + labels->step*i);
|
||||
|
||||
for( int j = 0; j < src->cols; j++ )
|
||||
if( srcptr[j] == 0 )
|
||||
labelptr[j] = k++;
|
||||
}
|
||||
}
|
||||
|
||||
icvDistanceTransformEx_5x5_C1R( src->data.ptr, src->step, temp->data.i, temp->step,
|
||||
dst->data.fl, dst->step, labels->data.i, labels->step, size, _mask );
|
||||
}
|
||||
|
||||
distanceTransformEx_5x5( src, temp, dst, labels, _mask );
|
||||
}
|
||||
}
|
||||
|
||||
void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labels,
|
||||
int distanceType, int maskSize, int labelType )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
_dst.create(src.size(), CV_32F);
|
||||
_labels.create(src.size(), CV_32S);
|
||||
CvMat c_src = src, c_dst = _dst.getMat(), c_labels = _labels.getMat();
|
||||
cvDistTransform(&c_src, &c_dst, distanceType, maskSize, 0, &c_labels, labelType);
|
||||
}
|
||||
|
||||
void cv::distanceTransform( InputArray _src, OutputArray _dst,
|
||||
int distanceType, int maskSize )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
_dst.create(src.size(), CV_32F);
|
||||
Mat dst = _dst.getMat();
|
||||
CvMat c_src = src, c_dst = _dst.getMat();
|
||||
cvDistTransform(&c_src, &c_dst, distanceType, maskSize, 0, 0, -1);
|
||||
distanceTransform(_src, _dst, noArray(), distanceType, maskSize, DIST_LABEL_PIXEL);
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL void
|
||||
cvDistTransform( const void* srcarr, void* dstarr,
|
||||
int distType, int maskSize,
|
||||
const float * /*mask*/,
|
||||
void* labelsarr, int labelType )
|
||||
{
|
||||
cv::Mat src = cv::cvarrToMat(srcarr);
|
||||
const cv::Mat dst = cv::cvarrToMat(dstarr);
|
||||
const cv::Mat labels = cv::cvarrToMat(labelsarr);
|
||||
|
||||
cv::distanceTransform(src, dst, labelsarr ? cv::_OutputArray(labels) : cv::_OutputArray(),
|
||||
distType, maskSize, labelType);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* End of file. */
|
||||
|
@ -7,10 +7,11 @@
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -23,7 +24,7 @@
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// * 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
|
||||
@ -41,7 +42,10 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
typedef struct CvFFillSegment
|
||||
namespace cv
|
||||
{
|
||||
|
||||
struct FFillSegment
|
||||
{
|
||||
ushort y;
|
||||
ushort l;
|
||||
@ -49,11 +53,13 @@ typedef struct CvFFillSegment
|
||||
ushort prevl;
|
||||
ushort prevr;
|
||||
short dir;
|
||||
}
|
||||
CvFFillSegment;
|
||||
};
|
||||
|
||||
#define UP 1
|
||||
#define DOWN -1
|
||||
enum
|
||||
{
|
||||
UP = 1,
|
||||
DOWN = -1
|
||||
};
|
||||
|
||||
#define ICV_PUSH( Y, L, R, PREV_L, PREV_R, DIR ) \
|
||||
{ \
|
||||
@ -65,7 +71,7 @@ CvFFillSegment;
|
||||
tail->dir = (short)(DIR); \
|
||||
if( ++tail == buffer_end ) \
|
||||
{ \
|
||||
buffer->resize(buffer->size() * 2); \
|
||||
buffer->resize(buffer->size() * 3/2); \
|
||||
tail = &buffer->front() + (tail - head); \
|
||||
head = &buffer->front(); \
|
||||
buffer_end = head + buffer->size(); \
|
||||
@ -83,23 +89,52 @@ CvFFillSegment;
|
||||
DIR = tail->dir; \
|
||||
}
|
||||
|
||||
/****************************************************************************************\
|
||||
* Simple Floodfill (repainting single-color connected component) *
|
||||
\****************************************************************************************/
|
||||
struct ConnectedComp
|
||||
{
|
||||
ConnectedComp();
|
||||
Rect rect;
|
||||
Point pt;
|
||||
int threshold;
|
||||
int label;
|
||||
int area;
|
||||
int harea;
|
||||
int carea;
|
||||
int perimeter;
|
||||
int nholes;
|
||||
int ninflections;
|
||||
double mx;
|
||||
double my;
|
||||
Scalar avg;
|
||||
Scalar sdv;
|
||||
};
|
||||
|
||||
ConnectedComp::ConnectedComp()
|
||||
{
|
||||
rect = Rect(0, 0, 0, 0);
|
||||
pt = Point(-1, -1);
|
||||
threshold = -1;
|
||||
label = -1;
|
||||
area = harea = carea = perimeter = nholes = ninflections = 0;
|
||||
mx = my = 0;
|
||||
avg = sdv = Scalar::all(0);
|
||||
}
|
||||
|
||||
// Simple Floodfill (repainting single-color connected component)
|
||||
|
||||
template<typename _Tp>
|
||||
static void
|
||||
icvFloodFill_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed,
|
||||
_Tp newVal, CvConnectedComp* region, int flags,
|
||||
std::vector<CvFFillSegment>* buffer )
|
||||
floodFill_CnIR( Mat& image, Point seed,
|
||||
_Tp newVal, ConnectedComp* region, int flags,
|
||||
std::vector<FFillSegment>* buffer )
|
||||
{
|
||||
typedef typename cv::DataType<_Tp>::channel_type _CTp;
|
||||
_Tp* img = (_Tp*)(pImage + step * seed.y);
|
||||
typedef typename DataType<_Tp>::channel_type _CTp;
|
||||
_Tp* img = (_Tp*)(image.data + image.step * seed.y);
|
||||
Size roi = image.size();
|
||||
int i, L, R;
|
||||
int area = 0;
|
||||
int XMin, XMax, YMin = seed.y, YMax = seed.y;
|
||||
int _8_connectivity = (flags & 255) == 8;
|
||||
CvFFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front();
|
||||
FFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front();
|
||||
|
||||
L = R = XMin = XMax = seed.x;
|
||||
|
||||
@ -142,7 +177,7 @@ icvFloodFill_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed,
|
||||
for( k = 0; k < 3; k++ )
|
||||
{
|
||||
dir = data[k][0];
|
||||
img = (_Tp*)(pImage + (YC + dir) * step);
|
||||
img = (_Tp*)(image.data + (YC + dir) * image.step);
|
||||
int left = data[k][1];
|
||||
int right = data[k][2];
|
||||
|
||||
@ -169,12 +204,12 @@ icvFloodFill_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed,
|
||||
|
||||
if( region )
|
||||
{
|
||||
region->pt = seed;
|
||||
region->area = area;
|
||||
region->rect.x = XMin;
|
||||
region->rect.y = YMin;
|
||||
region->rect.width = XMax - XMin + 1;
|
||||
region->rect.height = YMax - YMin + 1;
|
||||
region->value = cv::Scalar(newVal);
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,12 +227,12 @@ struct Diff8uC1
|
||||
|
||||
struct Diff8uC3
|
||||
{
|
||||
Diff8uC3(cv::Vec3b _lo, cv::Vec3b _up)
|
||||
Diff8uC3(Vec3b _lo, Vec3b _up)
|
||||
{
|
||||
for( int k = 0; k < 3; k++ )
|
||||
lo[k] = _lo[k], interval[k] = _lo[k] + _up[k];
|
||||
}
|
||||
bool operator()(const cv::Vec3b* a, const cv::Vec3b* b) const
|
||||
bool operator()(const Vec3b* a, const Vec3b* b) const
|
||||
{
|
||||
return (unsigned)(a[0][0] - b[0][0] + lo[0]) <= interval[0] &&
|
||||
(unsigned)(a[0][1] - b[0][1] + lo[1]) <= interval[1] &&
|
||||
@ -233,37 +268,30 @@ struct DiffC3
|
||||
};
|
||||
|
||||
typedef DiffC1<int> Diff32sC1;
|
||||
typedef DiffC3<cv::Vec3i> Diff32sC3;
|
||||
typedef DiffC3<Vec3i> Diff32sC3;
|
||||
typedef DiffC1<float> Diff32fC1;
|
||||
typedef DiffC3<cv::Vec3f> Diff32fC3;
|
||||
typedef DiffC3<Vec3f> Diff32fC3;
|
||||
|
||||
static cv::Vec3i& operator += (cv::Vec3i& a, const cv::Vec3b& b)
|
||||
{
|
||||
a[0] += b[0];
|
||||
a[1] += b[1];
|
||||
a[2] += b[2];
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _WTp, class Diff>
|
||||
template<typename _Tp, typename _MTp, typename _WTp, class Diff>
|
||||
static void
|
||||
icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep,
|
||||
CvSize /*roi*/, CvPoint seed, _Tp newVal, Diff diff,
|
||||
CvConnectedComp* region, int flags,
|
||||
std::vector<CvFFillSegment>* buffer )
|
||||
floodFillGrad_CnIR( Mat& image, Mat& msk,
|
||||
Point seed, _Tp newVal, _MTp newMaskVal,
|
||||
Diff diff, ConnectedComp* region, int flags,
|
||||
std::vector<FFillSegment>* buffer )
|
||||
{
|
||||
typedef typename cv::DataType<_Tp>::channel_type _CTp;
|
||||
typedef typename DataType<_Tp>::channel_type _CTp;
|
||||
int step = (int)image.step, maskStep = (int)msk.step;
|
||||
uchar* pImage = image.data;
|
||||
_Tp* img = (_Tp*)(pImage + step*seed.y);
|
||||
uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y;
|
||||
uchar* pMask = msk.data + maskStep + sizeof(_MTp);
|
||||
_MTp* mask = (_MTp*)(pMask + maskStep*seed.y);
|
||||
int i, L, R;
|
||||
int area = 0;
|
||||
_WTp sum = _WTp((typename cv::DataType<_Tp>::channel_type)0);
|
||||
int XMin, XMax, YMin = seed.y, YMax = seed.y;
|
||||
int _8_connectivity = (flags & 255) == 8;
|
||||
int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE;
|
||||
int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0;
|
||||
uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1);
|
||||
CvFFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front();
|
||||
int fixedRange = flags & FLOODFILL_FIXED_RANGE;
|
||||
int fillImage = (flags & FLOODFILL_MASK_ONLY) == 0;
|
||||
FFillSegment* buffer_end = &buffer->front() + buffer->size(), *head = &buffer->front(), *tail = &buffer->front();
|
||||
|
||||
L = R = seed.x;
|
||||
if( mask[L] )
|
||||
@ -323,7 +351,7 @@ icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep,
|
||||
dir = data[k][0];
|
||||
img = (_Tp*)(pImage + (YC + dir) * step);
|
||||
_Tp* img1 = (_Tp*)(pImage + YC * step);
|
||||
mask = pMask + (YC + dir) * maskStep;
|
||||
mask = (_MTp*)(pMask + (YC + dir) * maskStep);
|
||||
int left = data[k][1];
|
||||
int right = data[k][2];
|
||||
|
||||
@ -354,7 +382,7 @@ icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep,
|
||||
mask[j] = newMaskVal;
|
||||
|
||||
while( !mask[++i] &&
|
||||
(diff( img + i, img + (i-1) ) ||
|
||||
(diff( img + i, img + (i-1) ) ||
|
||||
(diff( img + i, img1 + i) && i <= R)))
|
||||
mask[i] = newMaskVal;
|
||||
|
||||
@ -368,13 +396,13 @@ icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep,
|
||||
_Tp val;
|
||||
|
||||
if( !mask[i] &&
|
||||
(((val = img[i],
|
||||
(unsigned)(idx = i-L-1) <= length) &&
|
||||
diff( &val, img1 + (i-1))) ||
|
||||
(((val = img[i],
|
||||
(unsigned)(idx = i-L-1) <= length) &&
|
||||
diff( &val, img1 + (i-1))) ||
|
||||
((unsigned)(++idx) <= length &&
|
||||
diff( &val, img1 + i )) ||
|
||||
diff( &val, img1 + i )) ||
|
||||
((unsigned)(++idx) <= length &&
|
||||
diff( &val, img1 + (i+1) ))))
|
||||
diff( &val, img1 + (i+1) ))))
|
||||
{
|
||||
int j = i;
|
||||
mask[i] = newMaskVal;
|
||||
@ -382,14 +410,14 @@ icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep,
|
||||
mask[j] = newMaskVal;
|
||||
|
||||
while( !mask[++i] &&
|
||||
((val = img[i],
|
||||
diff( &val, img + (i-1) )) ||
|
||||
((val = img[i],
|
||||
diff( &val, img + (i-1) )) ||
|
||||
(((unsigned)(idx = i-L-1) <= length &&
|
||||
diff( &val, img1 + (i-1) ))) ||
|
||||
diff( &val, img1 + (i-1) ))) ||
|
||||
((unsigned)(++idx) <= length &&
|
||||
diff( &val, img1 + i )) ||
|
||||
diff( &val, img1 + i )) ||
|
||||
((unsigned)(++idx) <= length &&
|
||||
diff( &val, img1 + (i+1) ))))
|
||||
diff( &val, img1 + (i+1) ))))
|
||||
mask[i] = newMaskVal;
|
||||
|
||||
ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
|
||||
@ -401,56 +429,40 @@ icvFloodFillGrad_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep,
|
||||
if( fillImage )
|
||||
for( i = L; i <= R; i++ )
|
||||
img[i] = newVal;
|
||||
else if( region )
|
||||
for( i = L; i <= R; i++ )
|
||||
sum += img[i];
|
||||
/*else if( region )
|
||||
for( i = L; i <= R; i++ )
|
||||
sum += img[i];*/
|
||||
}
|
||||
|
||||
if( region )
|
||||
{
|
||||
region->pt = seed;
|
||||
region->label = saturate_cast<int>(newMaskVal);
|
||||
region->area = area;
|
||||
region->rect.x = XMin;
|
||||
region->rect.y = YMin;
|
||||
region->rect.width = XMax - XMin + 1;
|
||||
region->rect.height = YMax - YMin + 1;
|
||||
|
||||
if( fillImage )
|
||||
region->value = cv::Scalar(newVal);
|
||||
else
|
||||
{
|
||||
double iarea = area ? 1./area : 0;
|
||||
region->value = cv::Scalar(sum*iarea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************************\
|
||||
* External Functions *
|
||||
\****************************************************************************************/
|
||||
|
||||
typedef void (*CvFloodFillFunc)(
|
||||
void* img, int step, CvSize size, CvPoint seed, void* newval,
|
||||
CvConnectedComp* comp, int flags, void* buffer, int cn );
|
||||
|
||||
typedef void (*CvFloodFillGradFunc)(
|
||||
void* img, int step, uchar* mask, int maskStep, CvSize size,
|
||||
CvPoint seed, void* newval, void* d_lw, void* d_up, void* ccomp,
|
||||
int flags, void* buffer, int cn );
|
||||
|
||||
CV_IMPL void
|
||||
cvFloodFill( CvArr* arr, CvPoint seed_point,
|
||||
CvScalar newVal, CvScalar lo_diff, CvScalar up_diff,
|
||||
CvConnectedComp* comp, int flags, CvArr* maskarr )
|
||||
int cv::floodFill( InputOutputArray _image, InputOutputArray _mask,
|
||||
Point seedPoint, Scalar newVal, Rect* rect,
|
||||
Scalar loDiff, Scalar upDiff, int flags )
|
||||
{
|
||||
cv::Ptr<CvMat> tempMask;
|
||||
std::vector<CvFFillSegment> buffer;
|
||||
ConnectedComp comp;
|
||||
vector<FFillSegment> buffer;
|
||||
|
||||
if( comp )
|
||||
memset( comp, 0, sizeof(*comp) );
|
||||
if( rect )
|
||||
*rect = Rect();
|
||||
|
||||
int i, type, depth, cn, is_simple;
|
||||
int buffer_size, connectivity = flags & 255;
|
||||
int i, connectivity = flags & 255;
|
||||
union {
|
||||
uchar b[4];
|
||||
int i[4];
|
||||
@ -459,191 +471,176 @@ cvFloodFill( CvArr* arr, CvPoint seed_point,
|
||||
} nv_buf;
|
||||
nv_buf._[0] = nv_buf._[1] = nv_buf._[2] = nv_buf._[3] = 0;
|
||||
|
||||
struct { cv::Vec3b b; cv::Vec3i i; cv::Vec3f f; } ld_buf, ud_buf;
|
||||
CvMat stub, *img = cvGetMat(arr, &stub);
|
||||
CvMat maskstub, *mask = (CvMat*)maskarr;
|
||||
CvSize size;
|
||||
struct { Vec3b b; Vec3i i; Vec3f f; } ld_buf, ud_buf;
|
||||
Mat img = _image.getMat(), mask;
|
||||
if( !_mask.empty() )
|
||||
mask = _mask.getMat();
|
||||
Size size = img.size();
|
||||
|
||||
type = CV_MAT_TYPE( img->type );
|
||||
depth = CV_MAT_DEPTH(type);
|
||||
cn = CV_MAT_CN(type);
|
||||
int type = img.type();
|
||||
int depth = img.depth();
|
||||
int cn = img.channels();
|
||||
|
||||
if( connectivity == 0 )
|
||||
connectivity = 4;
|
||||
else if( connectivity != 4 && connectivity != 8 )
|
||||
CV_Error( CV_StsBadFlag, "Connectivity must be 4, 0(=4) or 8" );
|
||||
|
||||
is_simple = mask == 0 && (flags & CV_FLOODFILL_MASK_ONLY) == 0;
|
||||
bool is_simple = mask.empty() && (flags & FLOODFILL_MASK_ONLY) == 0;
|
||||
|
||||
for( i = 0; i < cn; i++ )
|
||||
{
|
||||
if( lo_diff.val[i] < 0 || up_diff.val[i] < 0 )
|
||||
if( loDiff[i] < 0 || upDiff[i] < 0 )
|
||||
CV_Error( CV_StsBadArg, "lo_diff and up_diff must be non-negative" );
|
||||
is_simple &= fabs(lo_diff.val[i]) < DBL_EPSILON && fabs(up_diff.val[i]) < DBL_EPSILON;
|
||||
is_simple = is_simple && fabs(loDiff[i]) < DBL_EPSILON && fabs(upDiff[i]) < DBL_EPSILON;
|
||||
}
|
||||
|
||||
size = cvGetMatSize( img );
|
||||
|
||||
if( (unsigned)seed_point.x >= (unsigned)size.width ||
|
||||
(unsigned)seed_point.y >= (unsigned)size.height )
|
||||
if( (unsigned)seedPoint.x >= (unsigned)size.width ||
|
||||
(unsigned)seedPoint.y >= (unsigned)size.height )
|
||||
CV_Error( CV_StsOutOfRange, "Seed point is outside of image" );
|
||||
|
||||
cvScalarToRawData( &newVal, &nv_buf, type, 0 );
|
||||
buffer_size = MAX( size.width, size.height ) * 2;
|
||||
scalarToRawData( newVal, &nv_buf, type, 0);
|
||||
size_t buffer_size = MAX( size.width, size.height ) * 2;
|
||||
buffer.resize( buffer_size );
|
||||
|
||||
if( is_simple )
|
||||
{
|
||||
int elem_size = CV_ELEM_SIZE(type);
|
||||
const uchar* seed_ptr = img->data.ptr + img->step*seed_point.y + elem_size*seed_point.x;
|
||||
int elem_size = img.elemSize();
|
||||
const uchar* seed_ptr = img.data + img.step*seedPoint.y + elem_size*seedPoint.x;
|
||||
|
||||
for(i = 0; i < elem_size; i++)
|
||||
if (seed_ptr[i] != nv_buf.b[i])
|
||||
break;
|
||||
|
||||
if (i != elem_size)
|
||||
if( i != elem_size )
|
||||
{
|
||||
if( type == CV_8UC1 )
|
||||
icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, nv_buf.b[0],
|
||||
comp, flags, &buffer);
|
||||
floodFill_CnIR(img, seedPoint, nv_buf.b[0], &comp, flags, &buffer);
|
||||
else if( type == CV_8UC3 )
|
||||
icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, cv::Vec3b(nv_buf.b),
|
||||
comp, flags, &buffer);
|
||||
floodFill_CnIR(img, seedPoint, Vec3b(nv_buf.b), &comp, flags, &buffer);
|
||||
else if( type == CV_32SC1 )
|
||||
icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, nv_buf.i[0],
|
||||
comp, flags, &buffer);
|
||||
floodFill_CnIR(img, seedPoint, nv_buf.i[0], &comp, flags, &buffer);
|
||||
else if( type == CV_32FC1 )
|
||||
icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, nv_buf.f[0],
|
||||
comp, flags, &buffer);
|
||||
floodFill_CnIR(img, seedPoint, nv_buf.f[0], &comp, flags, &buffer);
|
||||
else if( type == CV_32SC3 )
|
||||
icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, cv::Vec3i(nv_buf.i),
|
||||
comp, flags, &buffer);
|
||||
floodFill_CnIR(img, seedPoint, Vec3i(nv_buf.i), &comp, flags, &buffer);
|
||||
else if( type == CV_32FC3 )
|
||||
icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, cv::Vec3f(nv_buf.f),
|
||||
comp, flags, &buffer);
|
||||
floodFill_CnIR(img, seedPoint, Vec3f(nv_buf.f), &comp, flags, &buffer);
|
||||
else
|
||||
CV_Error( CV_StsUnsupportedFormat, "" );
|
||||
return;
|
||||
if( rect )
|
||||
*rect = comp.rect;
|
||||
return comp.area;
|
||||
}
|
||||
}
|
||||
|
||||
if( !mask )
|
||||
if( mask.empty() )
|
||||
{
|
||||
/* created mask will be 8-byte aligned */
|
||||
tempMask = cvCreateMat( size.height + 2, (size.width + 9) & -8, CV_8UC1 );
|
||||
Mat tempMask( size.height + 2, size.width + 2, CV_8UC1 );
|
||||
tempMask.setTo(Scalar::all(0));
|
||||
mask = tempMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = cvGetMat( mask, &maskstub );
|
||||
if( !CV_IS_MASK_ARR( mask ))
|
||||
CV_Error( CV_StsBadMask, "" );
|
||||
|
||||
if( mask->width != size.width + 2 || mask->height != size.height + 2 )
|
||||
CV_Error( CV_StsUnmatchedSizes, "mask must be 2 pixel wider "
|
||||
"and 2 pixel taller than filled image" );
|
||||
CV_Assert( mask.rows == size.height+2 && mask.cols == size.width+2 );
|
||||
CV_Assert( mask.type() == CV_8U );
|
||||
}
|
||||
|
||||
int width = tempMask ? mask->step : size.width + 2;
|
||||
uchar* mask_row = mask->data.ptr + mask->step;
|
||||
memset( mask_row - mask->step, 1, width );
|
||||
memset( mask.data, 1, mask.cols );
|
||||
memset( mask.data + mask.step*(mask.rows-1), 1, mask.cols );
|
||||
|
||||
for( i = 1; i <= size.height; i++, mask_row += mask->step )
|
||||
for( i = 1; i <= size.height; i++ )
|
||||
{
|
||||
if( tempMask )
|
||||
memset( mask_row, 0, width );
|
||||
mask_row[0] = mask_row[size.width+1] = (uchar)1;
|
||||
mask.at<uchar>(i, 0) = mask.at<uchar>(i, mask.cols-1) = (uchar)1;
|
||||
}
|
||||
memset( mask_row, 1, width );
|
||||
|
||||
if( depth == CV_8U )
|
||||
for( i = 0; i < cn; i++ )
|
||||
{
|
||||
int t = cvFloor(lo_diff.val[i]);
|
||||
ld_buf.b[i] = CV_CAST_8U(t);
|
||||
t = cvFloor(up_diff.val[i]);
|
||||
ud_buf.b[i] = CV_CAST_8U(t);
|
||||
ld_buf.b[i] = saturate_cast<uchar>(cvFloor(loDiff[i]));
|
||||
ud_buf.b[i] = saturate_cast<uchar>(cvFloor(upDiff[i]));
|
||||
}
|
||||
else if( depth == CV_32S )
|
||||
for( i = 0; i < cn; i++ )
|
||||
{
|
||||
int t = cvFloor(lo_diff.val[i]);
|
||||
ld_buf.i[i] = t;
|
||||
t = cvFloor(up_diff.val[i]);
|
||||
ud_buf.i[i] = t;
|
||||
ld_buf.i[i] = cvFloor(loDiff[i]);
|
||||
ud_buf.i[i] = cvFloor(upDiff[i]);
|
||||
}
|
||||
else if( depth == CV_32F )
|
||||
for( i = 0; i < cn; i++ )
|
||||
{
|
||||
ld_buf.f[i] = (float)lo_diff.val[i];
|
||||
ud_buf.f[i] = (float)up_diff.val[i];
|
||||
ld_buf.f[i] = (float)loDiff[i];
|
||||
ud_buf.f[i] = (float)upDiff[i];
|
||||
}
|
||||
else
|
||||
CV_Error( CV_StsUnsupportedFormat, "" );
|
||||
|
||||
uchar newMaskVal = (uchar)((flags & ~0xff) == 0 ? 1 : ((flags >> 8) & 255));
|
||||
|
||||
if( type == CV_8UC1 )
|
||||
icvFloodFillGrad_CnIR<uchar, int, Diff8uC1>(
|
||||
img->data.ptr, img->step, mask->data.ptr, mask->step,
|
||||
size, seed_point, nv_buf.b[0],
|
||||
Diff8uC1(ld_buf.b[0], ud_buf.b[0]),
|
||||
comp, flags, &buffer);
|
||||
floodFillGrad_CnIR<uchar, uchar, int, Diff8uC1>(
|
||||
img, mask, seedPoint, nv_buf.b[0], newMaskVal,
|
||||
Diff8uC1(ld_buf.b[0], ud_buf.b[0]),
|
||||
&comp, flags, &buffer);
|
||||
else if( type == CV_8UC3 )
|
||||
icvFloodFillGrad_CnIR<cv::Vec3b, cv::Vec3i, Diff8uC3>(
|
||||
img->data.ptr, img->step, mask->data.ptr, mask->step,
|
||||
size, seed_point, cv::Vec3b(nv_buf.b),
|
||||
Diff8uC3(ld_buf.b, ud_buf.b),
|
||||
comp, flags, &buffer);
|
||||
floodFillGrad_CnIR<Vec3b, uchar, Vec3i, Diff8uC3>(
|
||||
img, mask, seedPoint, Vec3b(nv_buf.b), newMaskVal,
|
||||
Diff8uC3(ld_buf.b, ud_buf.b),
|
||||
&comp, flags, &buffer);
|
||||
else if( type == CV_32SC1 )
|
||||
icvFloodFillGrad_CnIR<int, int, Diff32sC1>(
|
||||
img->data.ptr, img->step, mask->data.ptr, mask->step,
|
||||
size, seed_point, nv_buf.i[0],
|
||||
Diff32sC1(ld_buf.i[0], ud_buf.i[0]),
|
||||
comp, flags, &buffer);
|
||||
floodFillGrad_CnIR<int, uchar, int, Diff32sC1>(
|
||||
img, mask, seedPoint, nv_buf.i[0], newMaskVal,
|
||||
Diff32sC1(ld_buf.i[0], ud_buf.i[0]),
|
||||
&comp, flags, &buffer);
|
||||
else if( type == CV_32SC3 )
|
||||
icvFloodFillGrad_CnIR<cv::Vec3i, cv::Vec3i, Diff32sC3>(
|
||||
img->data.ptr, img->step, mask->data.ptr, mask->step,
|
||||
size, seed_point, cv::Vec3i(nv_buf.i),
|
||||
Diff32sC3(ld_buf.i, ud_buf.i),
|
||||
comp, flags, &buffer);
|
||||
floodFillGrad_CnIR<Vec3i, uchar, Vec3i, Diff32sC3>(
|
||||
img, mask, seedPoint, Vec3i(nv_buf.i), newMaskVal,
|
||||
Diff32sC3(ld_buf.i, ud_buf.i),
|
||||
&comp, flags, &buffer);
|
||||
else if( type == CV_32FC1 )
|
||||
icvFloodFillGrad_CnIR<float, float, Diff32fC1>(
|
||||
img->data.ptr, img->step, mask->data.ptr, mask->step,
|
||||
size, seed_point, nv_buf.f[0],
|
||||
Diff32fC1(ld_buf.f[0], ud_buf.f[0]),
|
||||
comp, flags, &buffer);
|
||||
floodFillGrad_CnIR<float, uchar, float, Diff32fC1>(
|
||||
img, mask, seedPoint, nv_buf.f[0], newMaskVal,
|
||||
Diff32fC1(ld_buf.f[0], ud_buf.f[0]),
|
||||
&comp, flags, &buffer);
|
||||
else if( type == CV_32FC3 )
|
||||
icvFloodFillGrad_CnIR<cv::Vec3f, cv::Vec3f, Diff32fC3>(
|
||||
img->data.ptr, img->step, mask->data.ptr, mask->step,
|
||||
size, seed_point, cv::Vec3f(nv_buf.f),
|
||||
Diff32fC3(ld_buf.f, ud_buf.f),
|
||||
comp, flags, &buffer);
|
||||
floodFillGrad_CnIR<Vec3f, uchar, Vec3f, Diff32fC3>(
|
||||
img, mask, seedPoint, Vec3f(nv_buf.f), newMaskVal,
|
||||
Diff32fC3(ld_buf.f, ud_buf.f),
|
||||
&comp, flags, &buffer);
|
||||
else
|
||||
CV_Error(CV_StsUnsupportedFormat, "");
|
||||
|
||||
if( rect )
|
||||
*rect = comp.rect;
|
||||
return comp.area;
|
||||
}
|
||||
|
||||
|
||||
int cv::floodFill( InputOutputArray _image, Point seedPoint,
|
||||
Scalar newVal, Rect* rect,
|
||||
Scalar loDiff, Scalar upDiff, int flags )
|
||||
Scalar newVal, Rect* rect,
|
||||
Scalar loDiff, Scalar upDiff, int flags )
|
||||
{
|
||||
CvConnectedComp ccomp;
|
||||
CvMat c_image = _image.getMat();
|
||||
cvFloodFill(&c_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, 0);
|
||||
if( rect )
|
||||
*rect = ccomp.rect;
|
||||
return cvRound(ccomp.area);
|
||||
return floodFill(_image, Mat(), seedPoint, newVal, rect, loDiff, upDiff, flags);
|
||||
}
|
||||
|
||||
int cv::floodFill( InputOutputArray _image, InputOutputArray _mask,
|
||||
Point seedPoint, Scalar newVal, Rect* rect,
|
||||
Scalar loDiff, Scalar upDiff, int flags )
|
||||
|
||||
CV_IMPL void
|
||||
cvFloodFill( CvArr* arr, CvPoint seed_point,
|
||||
CvScalar newVal, CvScalar lo_diff, CvScalar up_diff,
|
||||
CvConnectedComp* comp, int flags, CvArr* maskarr )
|
||||
{
|
||||
CvConnectedComp ccomp;
|
||||
CvMat c_image = _image.getMat(), c_mask = _mask.getMat();
|
||||
cvFloodFill(&c_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, c_mask.data.ptr ? &c_mask : 0);
|
||||
if( rect )
|
||||
*rect = ccomp.rect;
|
||||
return cvRound(ccomp.area);
|
||||
if( comp )
|
||||
memset( comp, 0, sizeof(*comp) );
|
||||
|
||||
cv::Mat img = cv::cvarrToMat(arr), mask = cv::cvarrToMat(maskarr);
|
||||
int area = cv::floodFill(img, mask, seed_point, newVal,
|
||||
comp ? (cv::Rect*)&comp->rect : 0,
|
||||
lo_diff, up_diff, flags );
|
||||
if( comp )
|
||||
{
|
||||
comp->area = area;
|
||||
comp->value = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
|
@ -7,10 +7,11 @@
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -23,7 +24,7 @@
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// * 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
|
||||
@ -40,38 +41,26 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "_list.h"
|
||||
|
||||
#define halfPi ((float)(CV_PI*0.5))
|
||||
#define Pi ((float)CV_PI)
|
||||
#define a0 0 /*-4.172325e-7f*/ /*(-(float)0x7)/((float)0x1000000); */
|
||||
#define a1 1.000025f /*((float)0x1922253)/((float)0x1000000)*2/Pi; */
|
||||
#define a2 -2.652905e-4f /*(-(float)0x2ae6)/((float)0x1000000)*4/(Pi*Pi); */
|
||||
#define a3 -0.165624f /*(-(float)0xa45511)/((float)0x1000000)*8/(Pi*Pi*Pi); */
|
||||
#define a4 -1.964532e-3f /*(-(float)0x30fd3)/((float)0x1000000)*16/(Pi*Pi*Pi*Pi); */
|
||||
#define a5 1.02575e-2f /*((float)0x191cac)/((float)0x1000000)*32/(Pi*Pi*Pi*Pi*Pi); */
|
||||
#define a6 -9.580378e-4f /*(-(float)0x3af27)/((float)0x1000000)*64/(Pi*Pi*Pi*Pi*Pi*Pi); */
|
||||
namespace cv
|
||||
{
|
||||
|
||||
#define _sin(x) ((((((a6*(x) + a5)*(x) + a4)*(x) + a3)*(x) + a2)*(x) + a1)*(x) + a0)
|
||||
#define _cos(x) _sin(halfPi - (x))
|
||||
|
||||
/****************************************************************************************\
|
||||
* Classical Hough Transform *
|
||||
\****************************************************************************************/
|
||||
|
||||
typedef struct CvLinePolar
|
||||
// Classical Hough Transform
|
||||
struct LinePolar
|
||||
{
|
||||
float rho;
|
||||
float angle;
|
||||
}
|
||||
CvLinePolar;
|
||||
};
|
||||
|
||||
/*=====================================================================================*/
|
||||
|
||||
#define hough_cmp_gt(l1,l2) (aux[l1] > aux[l2])
|
||||
|
||||
static CV_IMPLEMENT_QSORT_EX( icvHoughSortDescent32s, int, hough_cmp_gt, const int* )
|
||||
struct hough_cmp_gt
|
||||
{
|
||||
hough_cmp_gt(const int* _aux) : aux(_aux) {}
|
||||
bool operator()(int l1, int l2) const { return aux[l1] > aux[l2]; }
|
||||
const int* aux;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Here image is an input raster;
|
||||
step is it's step; size characterizes it's ROI;
|
||||
@ -82,35 +71,27 @@ array of (rho, theta) pairs. linesMax is the buffer size (number of pairs).
|
||||
Functions return the actual number of found lines.
|
||||
*/
|
||||
static void
|
||||
icvHoughLinesStandard( const CvMat* img, float rho, float theta,
|
||||
int threshold, CvSeq *lines, int linesMax )
|
||||
HoughLinesStandard( const Mat& img, float rho, float theta,
|
||||
int threshold, vector<Vec2f>& lines, int linesMax )
|
||||
{
|
||||
cv::AutoBuffer<int> _accum, _sort_buf;
|
||||
cv::AutoBuffer<float> _tabSin, _tabCos;
|
||||
|
||||
const uchar* image;
|
||||
int step, width, height;
|
||||
int numangle, numrho;
|
||||
int total = 0;
|
||||
int i, j;
|
||||
float irho = 1 / rho;
|
||||
double scale;
|
||||
|
||||
CV_Assert( CV_IS_MAT(img) && CV_MAT_TYPE(img->type) == CV_8UC1 );
|
||||
CV_Assert( img.type() == CV_8UC1 );
|
||||
|
||||
image = img->data.ptr;
|
||||
step = img->step;
|
||||
width = img->cols;
|
||||
height = img->rows;
|
||||
const uchar* image = img.data;
|
||||
int step = (int)img.step;
|
||||
int width = img.cols;
|
||||
int height = img.rows;
|
||||
|
||||
numangle = cvRound(CV_PI / theta);
|
||||
numrho = cvRound(((width + height) * 2 + 1) / rho);
|
||||
int numangle = cvRound(CV_PI / theta);
|
||||
int numrho = cvRound(((width + height) * 2 + 1) / rho);
|
||||
|
||||
_accum.allocate((numangle+2) * (numrho+2));
|
||||
_sort_buf.allocate(numangle * numrho);
|
||||
_tabSin.allocate(numangle);
|
||||
_tabCos.allocate(numangle);
|
||||
int *accum = _accum, *sort_buf = _sort_buf;
|
||||
AutoBuffer<int> _accum((numangle+2) * (numrho+2));
|
||||
vector<int> _sort_buf;
|
||||
AutoBuffer<float> _tabSin(numangle);
|
||||
AutoBuffer<float> _tabCos(numangle);
|
||||
int *accum = _accum;
|
||||
float *tabSin = _tabSin, *tabCos = _tabCos;
|
||||
|
||||
memset( accum, 0, sizeof(accum[0]) * (numangle+2) * (numrho+2) );
|
||||
@ -143,126 +124,108 @@ icvHoughLinesStandard( const CvMat* img, float rho, float theta,
|
||||
if( accum[base] > threshold &&
|
||||
accum[base] > accum[base - 1] && accum[base] >= accum[base + 1] &&
|
||||
accum[base] > accum[base - numrho - 2] && accum[base] >= accum[base + numrho + 2] )
|
||||
sort_buf[total++] = base;
|
||||
_sort_buf.push_back(base);
|
||||
}
|
||||
|
||||
// stage 3. sort the detected lines by accumulator value
|
||||
icvHoughSortDescent32s( sort_buf, total, accum );
|
||||
cv::sort(_sort_buf, hough_cmp_gt(accum));
|
||||
|
||||
// stage 4. store the first min(total,linesMax) lines to the output buffer
|
||||
linesMax = MIN(linesMax, total);
|
||||
scale = 1./(numrho+2);
|
||||
linesMax = min(linesMax, (int)_sort_buf.size());
|
||||
double scale = 1./(numrho+2);
|
||||
for( i = 0; i < linesMax; i++ )
|
||||
{
|
||||
CvLinePolar line;
|
||||
int idx = sort_buf[i];
|
||||
LinePolar line;
|
||||
int idx = _sort_buf[i];
|
||||
int n = cvFloor(idx*scale) - 1;
|
||||
int r = idx - (n+1)*(numrho+2) - 1;
|
||||
line.rho = (r - (numrho - 1)*0.5f) * rho;
|
||||
line.angle = n * theta;
|
||||
cvSeqPush( lines, &line );
|
||||
lines.push_back(Vec2f(line.rho, line.angle));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
* Multi-Scale variant of Classical Hough Transform *
|
||||
\****************************************************************************************/
|
||||
// Multi-Scale variant of Classical Hough Transform
|
||||
|
||||
//DECLARE_AND_IMPLEMENT_LIST( _index, h_ );
|
||||
IMPLEMENT_LIST( _index, h_ )
|
||||
|
||||
static void
|
||||
icvHoughLinesSDiv( const CvMat* img,
|
||||
float rho, float theta, int threshold,
|
||||
int srn, int stn,
|
||||
CvSeq* lines, int linesMax )
|
||||
struct hough_index
|
||||
{
|
||||
std::vector<uchar> _caccum, _buffer;
|
||||
std::vector<float> _sinTable;
|
||||
std::vector<int> _x, _y;
|
||||
float* sinTable;
|
||||
int *x, *y;
|
||||
uchar *caccum, *buffer;
|
||||
_CVLIST* list = 0;
|
||||
hough_index() : value(0), rho(0.f), theta(0.f) {}
|
||||
hough_index(int _val, float _rho, float _theta)
|
||||
: value(_val), rho(_rho), theta(_theta) {}
|
||||
|
||||
int value;
|
||||
float rho, theta;
|
||||
};
|
||||
|
||||
#define _POINT(row, column)\
|
||||
(image_src[(row)*step+(column)])
|
||||
|
||||
static void
|
||||
HoughLinesSDiv( const Mat& img,
|
||||
float rho, float theta, int threshold,
|
||||
int srn, int stn,
|
||||
vector<Vec2f>& lines, int linesMax )
|
||||
{
|
||||
#define _POINT(row, column)\
|
||||
(image_src[(row)*step+(column)])
|
||||
|
||||
uchar *mcaccum = 0;
|
||||
int rn, tn; /* number of rho and theta discrete values */
|
||||
int index, i;
|
||||
int ri, ti, ti1, ti0;
|
||||
int row, col;
|
||||
float r, t; /* Current rho and theta */
|
||||
float rv; /* Some temporary rho value */
|
||||
float irho;
|
||||
float itheta;
|
||||
float srho, stheta;
|
||||
float isrho, istheta;
|
||||
|
||||
const uchar* image_src;
|
||||
int w, h, step;
|
||||
int fn = 0;
|
||||
float xc, yc;
|
||||
|
||||
const float d2r = (float)(Pi / 180);
|
||||
const float d2r = (float)(CV_PI / 180);
|
||||
int sfn = srn * stn;
|
||||
int fi;
|
||||
int count;
|
||||
int cmax = 0;
|
||||
|
||||
CVPOS pos;
|
||||
_index *pindex;
|
||||
_index vi;
|
||||
vector<hough_index> lst;
|
||||
|
||||
CV_Assert( CV_IS_MAT(img) && CV_MAT_TYPE(img->type) == CV_8UC1 );
|
||||
CV_Assert( img.type() == CV_8UC1 );
|
||||
CV_Assert( linesMax > 0 && rho > 0 && theta > 0 );
|
||||
|
||||
threshold = MIN( threshold, 255 );
|
||||
|
||||
image_src = img->data.ptr;
|
||||
step = img->step;
|
||||
w = img->cols;
|
||||
h = img->rows;
|
||||
const uchar* image_src = img.data;
|
||||
int step = (int)img.step;
|
||||
int w = img.cols;
|
||||
int h = img.rows;
|
||||
|
||||
irho = 1 / rho;
|
||||
itheta = 1 / theta;
|
||||
srho = rho / srn;
|
||||
stheta = theta / stn;
|
||||
isrho = 1 / srho;
|
||||
istheta = 1 / stheta;
|
||||
float irho = 1 / rho;
|
||||
float itheta = 1 / theta;
|
||||
float srho = rho / srn;
|
||||
float stheta = theta / stn;
|
||||
float isrho = 1 / srho;
|
||||
float istheta = 1 / stheta;
|
||||
|
||||
rn = cvFloor( sqrt( (double)w * w + (double)h * h ) * irho );
|
||||
tn = cvFloor( 2 * Pi * itheta );
|
||||
int rn = cvFloor( sqrt( (double)w * w + (double)h * h ) * irho );
|
||||
int tn = cvFloor( 2 * CV_PI * itheta );
|
||||
|
||||
list = h_create_list__index( linesMax < 1000 ? linesMax : 1000 );
|
||||
vi.value = threshold;
|
||||
vi.rho = -1;
|
||||
h_add_head__index( list, &vi );
|
||||
lst.push_back(hough_index(threshold, -1.f, 0.f));
|
||||
|
||||
/* Precalculating sin */
|
||||
_sinTable.resize( 5 * tn * stn );
|
||||
sinTable = &_sinTable[0];
|
||||
// Precalculate sin table
|
||||
vector<float> _sinTable( 5 * tn * stn );
|
||||
float* sinTable = &_sinTable[0];
|
||||
|
||||
for( index = 0; index < 5 * tn * stn; index++ )
|
||||
sinTable[index] = (float)cos( stheta * index * 0.2f );
|
||||
|
||||
_caccum.resize(rn * tn);
|
||||
caccum = &_caccum[0];
|
||||
memset( caccum, 0, rn * tn * sizeof( caccum[0] ));
|
||||
vector<uchar> _caccum(rn * tn, (uchar)0);
|
||||
uchar* caccum = &_caccum[0];
|
||||
|
||||
/* Counting all feature pixels */
|
||||
// Counting all feature pixels
|
||||
for( row = 0; row < h; row++ )
|
||||
for( col = 0; col < w; col++ )
|
||||
fn += _POINT( row, col ) != 0;
|
||||
|
||||
_x.resize(fn);
|
||||
_y.resize(fn);
|
||||
x = &_x[0];
|
||||
y = &_y[0];
|
||||
vector<int> _x(fn), _y(fn);
|
||||
int* x = &_x[0], *y = &_y[0];
|
||||
|
||||
/* Full Hough Transform (it's accumulator update part) */
|
||||
// Full Hough Transform (it's accumulator update part)
|
||||
fi = 0;
|
||||
for( row = 0; row < h; row++ )
|
||||
{
|
||||
@ -275,9 +238,9 @@ icvHoughLinesSDiv( const CvMat* img,
|
||||
float scale_factor;
|
||||
int iprev = -1;
|
||||
float phi, phi1;
|
||||
float theta_it; /* Value of theta for iterating */
|
||||
float theta_it; // Value of theta for iterating
|
||||
|
||||
/* Remember the feature point */
|
||||
// Remember the feature point
|
||||
x[fi] = col;
|
||||
y[fi] = row;
|
||||
fi++;
|
||||
@ -289,18 +252,18 @@ icvHoughLinesSDiv( const CvMat* img,
|
||||
t = (float) fabs( cvFastArctan( yc, xc ) * d2r );
|
||||
r = (float) sqrt( (double)xc * xc + (double)yc * yc );
|
||||
r0 = r * irho;
|
||||
ti0 = cvFloor( (t + Pi / 2) * itheta );
|
||||
ti0 = cvFloor( (t + CV_PI*0.5) * itheta );
|
||||
|
||||
caccum[ti0]++;
|
||||
|
||||
theta_it = rho / r;
|
||||
theta_it = theta_it < theta ? theta_it : theta;
|
||||
scale_factor = theta_it * itheta;
|
||||
halftn = cvFloor( Pi / theta_it );
|
||||
for( ti1 = 1, phi = theta_it - halfPi, phi1 = (theta_it + t) * itheta;
|
||||
halftn = cvFloor( CV_PI / theta_it );
|
||||
for( ti1 = 1, phi = theta_it - (float)(CV_PI*0.5), phi1 = (theta_it + t) * itheta;
|
||||
ti1 < halftn; ti1++, phi += theta_it, phi1 += scale_factor )
|
||||
{
|
||||
rv = r0 * _cos( phi );
|
||||
rv = r0 * std::cos( phi );
|
||||
i = cvFloor( rv ) * tn;
|
||||
i += cvFloor( phi1 );
|
||||
assert( i >= 0 );
|
||||
@ -314,28 +277,26 @@ icvHoughLinesSDiv( const CvMat* img,
|
||||
}
|
||||
}
|
||||
|
||||
/* Starting additional analysis */
|
||||
// Starting additional analysis
|
||||
count = 0;
|
||||
for( ri = 0; ri < rn; ri++ )
|
||||
{
|
||||
for( ti = 0; ti < tn; ti++ )
|
||||
{
|
||||
if( caccum[ri * tn + ti] > threshold )
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( count * 100 > rn * tn )
|
||||
{
|
||||
icvHoughLinesStandard( img, rho, theta, threshold, lines, linesMax );
|
||||
HoughLinesStandard( img, rho, theta, threshold, lines, linesMax );
|
||||
return;
|
||||
}
|
||||
|
||||
_buffer.resize(srn * stn + 2);
|
||||
buffer = &_buffer[0];
|
||||
mcaccum = buffer + 1;
|
||||
vector<uchar> _buffer(srn * stn + 2);
|
||||
uchar* buffer = &_buffer[0];
|
||||
uchar* mcaccum = buffer + 1;
|
||||
|
||||
count = 0;
|
||||
for( ri = 0; ri < rn; ri++ )
|
||||
@ -355,18 +316,16 @@ icvHoughLinesSDiv( const CvMat* img,
|
||||
yc = (float) y[index] + 0.5f;
|
||||
xc = (float) x[index] + 0.5f;
|
||||
|
||||
/* Update the accumulator */
|
||||
// Update the accumulator
|
||||
t = (float) fabs( cvFastArctan( yc, xc ) * d2r );
|
||||
r = (float) sqrt( (double)xc * xc + (double)yc * yc ) * isrho;
|
||||
ti0 = cvFloor( (t + Pi * 0.5f) * istheta );
|
||||
ti0 = cvFloor( (t + CV_PI * 0.5) * istheta );
|
||||
ti2 = (ti * stn - ti0) * 5;
|
||||
r0 = (float) ri *srn;
|
||||
|
||||
for( ti1 = 0 /*, phi = ti*theta - Pi/2 - t */ ; ti1 < stn; ti1++, ti2 += 5
|
||||
/*phi += stheta */ )
|
||||
for( ti1 = 0; ti1 < stn; ti1++, ti2 += 5 )
|
||||
{
|
||||
/*rv = r*_cos(phi) - r0; */
|
||||
rv = r * sinTable[(int) (abs( ti2 ))] - r0;
|
||||
rv = r * sinTable[(int) (std::abs( ti2 ))] - r0;
|
||||
i = cvFloor( rv ) * stn + ti1;
|
||||
|
||||
i = CV_IMAX( i, -1 );
|
||||
@ -377,75 +336,38 @@ icvHoughLinesSDiv( const CvMat* img,
|
||||
}
|
||||
}
|
||||
|
||||
/* Find peaks in maccum... */
|
||||
// Find peaks in maccum...
|
||||
for( index = 0; index < sfn; index++ )
|
||||
{
|
||||
i = 0;
|
||||
pos = h_get_tail_pos__index( list );
|
||||
if( h_get_prev__index( &pos )->value < mcaccum[index] )
|
||||
int pos = (int)(lst.size() - 1);
|
||||
if( pos < 0 || lst[pos].value < mcaccum[index] )
|
||||
{
|
||||
vi.value = mcaccum[index];
|
||||
vi.rho = index / stn * srho + ri * rho;
|
||||
vi.theta = index % stn * stheta + ti * theta - halfPi;
|
||||
while( h_is_pos__index( pos ))
|
||||
hough_index vi(mcaccum[index],
|
||||
index / stn * srho + ri * rho,
|
||||
index % stn * stheta + ti * theta - (float)(CV_PI*0.5));
|
||||
lst.push_back(vi);
|
||||
for( ; pos >= 0; pos-- )
|
||||
{
|
||||
if( h_get__index( pos )->value > mcaccum[index] )
|
||||
{
|
||||
h_insert_after__index( list, pos, &vi );
|
||||
if( h_get_count__index( list ) > linesMax )
|
||||
{
|
||||
h_remove_tail__index( list );
|
||||
}
|
||||
if( lst[pos].value > vi.value )
|
||||
break;
|
||||
}
|
||||
h_get_prev__index( &pos );
|
||||
}
|
||||
if( !h_is_pos__index( pos ))
|
||||
{
|
||||
h_add_head__index( list, &vi );
|
||||
if( h_get_count__index( list ) > linesMax )
|
||||
{
|
||||
h_remove_tail__index( list );
|
||||
}
|
||||
lst[pos+1] = lst[pos];
|
||||
}
|
||||
lst[pos+1] = vi;
|
||||
if( (int)lst.size() > linesMax )
|
||||
lst.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos = h_get_head_pos__index( list );
|
||||
if( h_get_count__index( list ) == 1 )
|
||||
for( size_t idx = 0; idx < lst.size(); idx++ )
|
||||
{
|
||||
if( h_get__index( pos )->rho < 0 )
|
||||
{
|
||||
h_clear_list__index( list );
|
||||
}
|
||||
if( lst[idx].rho < 0 )
|
||||
continue;
|
||||
lines.push_back(Vec2f(lst[idx].rho, lst[idx].theta));
|
||||
}
|
||||
else
|
||||
{
|
||||
while( h_is_pos__index( pos ))
|
||||
{
|
||||
CvLinePolar line;
|
||||
pindex = h_get__index( pos );
|
||||
if( pindex->rho < 0 )
|
||||
{
|
||||
/* This should be the last element... */
|
||||
h_get_next__index( &pos );
|
||||
assert( !h_is_pos__index( pos ));
|
||||
break;
|
||||
}
|
||||
line.rho = pindex->rho;
|
||||
line.angle = pindex->theta;
|
||||
cvSeqPush( lines, &line );
|
||||
|
||||
if( lines->total >= linesMax )
|
||||
break;
|
||||
h_get_next__index( &pos );
|
||||
}
|
||||
}
|
||||
|
||||
h_destroy_list__index(list);
|
||||
}
|
||||
|
||||
|
||||
@ -454,98 +376,80 @@ icvHoughLinesSDiv( const CvMat* img,
|
||||
\****************************************************************************************/
|
||||
|
||||
static void
|
||||
icvHoughLinesProbabilistic( CvMat* image,
|
||||
float rho, float theta, int threshold,
|
||||
int lineLength, int lineGap,
|
||||
CvSeq *lines, int linesMax )
|
||||
HoughLinesProbabilistic( Mat& image,
|
||||
float rho, float theta, int threshold,
|
||||
int lineLength, int lineGap,
|
||||
vector<Vec4i>& lines, int linesMax )
|
||||
{
|
||||
cv::Mat accum, mask;
|
||||
cv::vector<float> trigtab;
|
||||
cv::MemStorage storage(cvCreateMemStorage(0));
|
||||
|
||||
CvSeq* seq;
|
||||
CvSeqWriter writer;
|
||||
int width, height;
|
||||
int numangle, numrho;
|
||||
float ang;
|
||||
int r, n, count;
|
||||
CvPoint pt;
|
||||
Point pt;
|
||||
float irho = 1 / rho;
|
||||
CvRNG rng = cvRNG(-1);
|
||||
const float* ttab;
|
||||
uchar* mdata0;
|
||||
RNG rng((uint64)-1);
|
||||
|
||||
CV_Assert( CV_IS_MAT(image) && CV_MAT_TYPE(image->type) == CV_8UC1 );
|
||||
CV_Assert( image.type() == CV_8UC1 );
|
||||
|
||||
width = image->cols;
|
||||
height = image->rows;
|
||||
int width = image.cols;
|
||||
int height = image.rows;
|
||||
|
||||
numangle = cvRound(CV_PI / theta);
|
||||
numrho = cvRound(((width + height) * 2 + 1) / rho);
|
||||
int numangle = cvRound(CV_PI / theta);
|
||||
int numrho = cvRound(((width + height) * 2 + 1) / rho);
|
||||
|
||||
accum.create( numangle, numrho, CV_32SC1 );
|
||||
mask.create( height, width, CV_8UC1 );
|
||||
trigtab.resize(numangle*2);
|
||||
accum = cv::Scalar(0);
|
||||
Mat accum = Mat::zeros( numangle, numrho, CV_32SC1 );
|
||||
Mat mask( height, width, CV_8UC1 );
|
||||
vector<float> trigtab(numangle*2);
|
||||
|
||||
for( ang = 0, n = 0; n < numangle; ang += theta, n++ )
|
||||
for( int n = 0; n < numangle; n++ )
|
||||
{
|
||||
trigtab[n*2] = (float)(cos(ang) * irho);
|
||||
trigtab[n*2+1] = (float)(sin(ang) * irho);
|
||||
trigtab[n*2] = (float)(cos((double)n*theta) * irho);
|
||||
trigtab[n*2+1] = (float)(sin((double)n*theta) * irho);
|
||||
}
|
||||
ttab = &trigtab[0];
|
||||
mdata0 = mask.data;
|
||||
|
||||
cvStartWriteSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage, &writer );
|
||||
const float* ttab = &trigtab[0];
|
||||
uchar* mdata0 = mask.data;
|
||||
vector<Point> nzloc;
|
||||
|
||||
// stage 1. collect non-zero image points
|
||||
for( pt.y = 0, count = 0; pt.y < height; pt.y++ )
|
||||
for( pt.y = 0; pt.y < height; pt.y++ )
|
||||
{
|
||||
const uchar* data = image->data.ptr + pt.y*image->step;
|
||||
uchar* mdata = mdata0 + pt.y*width;
|
||||
const uchar* data = image.ptr(pt.y);
|
||||
uchar* mdata = mask.ptr(pt.y);
|
||||
for( pt.x = 0; pt.x < width; pt.x++ )
|
||||
{
|
||||
if( data[pt.x] )
|
||||
{
|
||||
mdata[pt.x] = (uchar)1;
|
||||
CV_WRITE_SEQ_ELEM( pt, writer );
|
||||
nzloc.push_back(pt);
|
||||
}
|
||||
else
|
||||
mdata[pt.x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
seq = cvEndWriteSeq( &writer );
|
||||
count = seq->total;
|
||||
int count = (int)nzloc.size();
|
||||
|
||||
// stage 2. process all the points in random order
|
||||
for( ; count > 0; count-- )
|
||||
{
|
||||
// choose random point out of the remaining ones
|
||||
int idx = cvRandInt(&rng) % count;
|
||||
int idx = rng.uniform(0, count);
|
||||
int max_val = threshold-1, max_n = 0;
|
||||
CvPoint* point = (CvPoint*)cvGetSeqElem( seq, idx );
|
||||
CvPoint line_end[2] = {{0,0}, {0,0}};
|
||||
Point point = nzloc[idx];
|
||||
Point line_end[2];
|
||||
float a, b;
|
||||
int* adata = (int*)accum.data;
|
||||
int i, j, k, x0, y0, dx0, dy0, xflag;
|
||||
int i = point.y, j = point.x, k, x0, y0, dx0, dy0, xflag;
|
||||
int good_line;
|
||||
const int shift = 16;
|
||||
|
||||
i = point->y;
|
||||
j = point->x;
|
||||
|
||||
// "remove" it by overriding it with the last element
|
||||
*point = *(CvPoint*)cvGetSeqElem( seq, count-1 );
|
||||
nzloc[idx] = nzloc[count-1];
|
||||
|
||||
// check if it has been excluded already (i.e. belongs to some other line)
|
||||
if( !mdata0[i*width + j] )
|
||||
continue;
|
||||
|
||||
// update accumulator, find the most probable line
|
||||
for( n = 0; n < numangle; n++, adata += numrho )
|
||||
for( int n = 0; n < numangle; n++, adata += numrho )
|
||||
{
|
||||
r = cvRound( j * ttab[n*2] + i * ttab[n*2+1] );
|
||||
int r = cvRound( j * ttab[n*2] + i * ttab[n*2+1] );
|
||||
r += (numrho - 1) / 2;
|
||||
int val = ++adata[r];
|
||||
if( max_val < val )
|
||||
@ -625,8 +529,8 @@ icvHoughLinesProbabilistic( CvMat* image,
|
||||
}
|
||||
}
|
||||
|
||||
good_line = abs(line_end[1].x - line_end[0].x) >= lineLength ||
|
||||
abs(line_end[1].y - line_end[0].y) >= lineLength;
|
||||
good_line = std::abs(line_end[1].x - line_end[0].x) >= lineLength ||
|
||||
std::abs(line_end[1].y - line_end[0].y) >= lineLength;
|
||||
|
||||
for( k = 0; k < 2; k++ )
|
||||
{
|
||||
@ -664,9 +568,9 @@ icvHoughLinesProbabilistic( CvMat* image,
|
||||
if( good_line )
|
||||
{
|
||||
adata = (int*)accum.data;
|
||||
for( n = 0; n < numangle; n++, adata += numrho )
|
||||
for( int n = 0; n < numangle; n++, adata += numrho )
|
||||
{
|
||||
r = cvRound( j1 * ttab[n*2] + i1 * ttab[n*2+1] );
|
||||
int r = cvRound( j1 * ttab[n*2] + i1 * ttab[n*2+1] );
|
||||
r += (numrho - 1) / 2;
|
||||
adata[r]--;
|
||||
}
|
||||
@ -681,23 +585,56 @@ icvHoughLinesProbabilistic( CvMat* image,
|
||||
|
||||
if( good_line )
|
||||
{
|
||||
CvRect lr = { line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y };
|
||||
cvSeqPush( lines, &lr );
|
||||
if( lines->total >= linesMax )
|
||||
Vec4i lr(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y);
|
||||
lines.push_back(lr);
|
||||
if( (int)lines.size() >= linesMax )
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cv::HoughLines( InputArray _image, OutputArray _lines,
|
||||
double rho, double theta, int threshold,
|
||||
double srn, double stn )
|
||||
{
|
||||
Mat image = _image.getMat();
|
||||
vector<Vec2f> lines;
|
||||
|
||||
if( srn == 0 && stn == 0 )
|
||||
HoughLinesStandard(image, (float)rho, (float)theta, threshold, lines, INT_MAX);
|
||||
else
|
||||
HoughLinesSDiv(image, (float)rho, (float)theta, threshold, cvRound(srn), cvRound(stn), lines, INT_MAX);
|
||||
|
||||
Mat(lines).copyTo(_lines);
|
||||
}
|
||||
|
||||
|
||||
void cv::HoughLinesP(InputArray _image, OutputArray _lines,
|
||||
double rho, double theta, int threshold,
|
||||
double minLineLength, double maxGap )
|
||||
{
|
||||
Mat image = _image.getMat();
|
||||
vector<Vec4i> lines;
|
||||
HoughLinesProbabilistic(image, (float)rho, (float)theta, threshold, cvRound(minLineLength), cvRound(maxGap), lines, INT_MAX);
|
||||
Mat(lines).copyTo(_lines);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Wrapper function for standard hough transform */
|
||||
CV_IMPL CvSeq*
|
||||
cvHoughLines2( CvArr* src_image, void* lineStorage, int method,
|
||||
double rho, double theta, int threshold,
|
||||
double param1, double param2 )
|
||||
{
|
||||
cv::Mat image = cv::cvarrToMat(src_image);
|
||||
std::vector<cv::Vec2f> l2;
|
||||
std::vector<cv::Vec4i> l4;
|
||||
CvSeq* result = 0;
|
||||
|
||||
CvMat stub, *img = (CvMat*)src_image;
|
||||
CvMat* mat = 0;
|
||||
CvSeq* lines = 0;
|
||||
CvSeq lines_header;
|
||||
@ -706,11 +643,6 @@ cvHoughLines2( CvArr* src_image, void* lineStorage, int method,
|
||||
int linesMax = INT_MAX;
|
||||
int iparam1, iparam2;
|
||||
|
||||
img = cvGetMat( img, &stub );
|
||||
|
||||
if( !CV_IS_MASK_ARR(img))
|
||||
CV_Error( CV_StsBadArg, "The source image must be 8-bit, single-channel" );
|
||||
|
||||
if( !lineStorage )
|
||||
CV_Error( CV_StsNullPtr, "NULL destination" );
|
||||
|
||||
@ -758,31 +690,49 @@ cvHoughLines2( CvArr* src_image, void* lineStorage, int method,
|
||||
switch( method )
|
||||
{
|
||||
case CV_HOUGH_STANDARD:
|
||||
icvHoughLinesStandard( img, (float)rho,
|
||||
(float)theta, threshold, lines, linesMax );
|
||||
break;
|
||||
HoughLinesStandard( image, (float)rho,
|
||||
(float)theta, threshold, l2, linesMax );
|
||||
break;
|
||||
case CV_HOUGH_MULTI_SCALE:
|
||||
icvHoughLinesSDiv( img, (float)rho, (float)theta,
|
||||
threshold, iparam1, iparam2, lines, linesMax );
|
||||
break;
|
||||
HoughLinesSDiv( image, (float)rho, (float)theta,
|
||||
threshold, iparam1, iparam2, l2, linesMax );
|
||||
break;
|
||||
case CV_HOUGH_PROBABILISTIC:
|
||||
icvHoughLinesProbabilistic( img, (float)rho, (float)theta,
|
||||
threshold, iparam1, iparam2, lines, linesMax );
|
||||
break;
|
||||
HoughLinesProbabilistic( image, (float)rho, (float)theta,
|
||||
threshold, iparam1, iparam2, l4, linesMax );
|
||||
break;
|
||||
default:
|
||||
CV_Error( CV_StsBadArg, "Unrecognized method id" );
|
||||
}
|
||||
|
||||
int nlines = (int)(l2.size() + l4.size());
|
||||
|
||||
if( mat )
|
||||
{
|
||||
if( mat->cols > mat->rows )
|
||||
mat->cols = lines->total;
|
||||
mat->cols = nlines;
|
||||
else
|
||||
mat->rows = lines->total;
|
||||
mat->rows = nlines;
|
||||
}
|
||||
else
|
||||
result = lines;
|
||||
|
||||
if( nlines )
|
||||
{
|
||||
cv::Mat lx = method == CV_HOUGH_STANDARD || method == CV_HOUGH_MULTI_SCALE ?
|
||||
cv::Mat(nlines, 1, CV_32FC2, &l2[0]) : cv::Mat(nlines, 1, CV_32SC4, &l4[0]);
|
||||
|
||||
if( mat )
|
||||
{
|
||||
cv::Mat dst(nlines, 1, lx.type(), mat->data.ptr);
|
||||
lx.copyTo(dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
cvSeqPushMulti(lines, lx.data, nlines);
|
||||
}
|
||||
}
|
||||
|
||||
if( !mat )
|
||||
result = lines;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -909,7 +859,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
|
||||
sort_buf.resize( MAX(center_count,nz_count) );
|
||||
cvCvtSeqToArray( centers, &sort_buf[0] );
|
||||
|
||||
icvHoughSortDescent32s( &sort_buf[0], center_count, adata );
|
||||
std::sort(sort_buf.begin(), sort_buf.begin() + center_count, cv::hough_cmp_gt(adata));
|
||||
cvClearSeq( centers );
|
||||
cvSeqPushMulti( centers, &sort_buf[0], center_count );
|
||||
|
||||
@ -963,7 +913,7 @@ icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
|
||||
continue;
|
||||
dist_buf->cols = nz_count1;
|
||||
cvPow( dist_buf, dist_buf, 0.5 );
|
||||
icvHoughSortDescent32s( &sort_buf[0], nz_count1, (int*)ddata );
|
||||
std::sort(sort_buf.begin(), sort_buf.begin() + nz_count1, cv::hough_cmp_gt((int*)ddata));
|
||||
|
||||
dist_sum = start_dist = ddata[sort_buf[nz_count1-1]];
|
||||
for( j = nz_count1 - 2; j >= 0; j-- )
|
||||
@ -1102,31 +1052,6 @@ static void seqToMat(const CvSeq* seq, OutputArray _arr)
|
||||
|
||||
}
|
||||
|
||||
void cv::HoughLines( InputArray _image, OutputArray _lines,
|
||||
double rho, double theta, int threshold,
|
||||
double srn, double stn )
|
||||
{
|
||||
Ptr<CvMemStorage> storage = cvCreateMemStorage(STORAGE_SIZE);
|
||||
Mat image = _image.getMat();
|
||||
CvMat c_image = image;
|
||||
CvSeq* seq = cvHoughLines2( &c_image, storage, srn == 0 && stn == 0 ?
|
||||
CV_HOUGH_STANDARD : CV_HOUGH_MULTI_SCALE,
|
||||
rho, theta, threshold, srn, stn );
|
||||
seqToMat(seq, _lines);
|
||||
}
|
||||
|
||||
void cv::HoughLinesP( InputArray _image, OutputArray _lines,
|
||||
double rho, double theta, int threshold,
|
||||
double minLineLength, double maxGap )
|
||||
{
|
||||
Ptr<CvMemStorage> storage = cvCreateMemStorage(STORAGE_SIZE);
|
||||
Mat image = _image.getMat();
|
||||
CvMat c_image = image;
|
||||
CvSeq* seq = cvHoughLines2( &c_image, storage, CV_HOUGH_PROBABILISTIC,
|
||||
rho, theta, threshold, minLineLength, maxGap );
|
||||
seqToMat(seq, _lines);
|
||||
}
|
||||
|
||||
void cv::HoughCircles( InputArray _image, OutputArray _circles,
|
||||
int method, double dp, double min_dist,
|
||||
double param1, double param2,
|
||||
|
@ -2891,10 +2891,10 @@ class RemapInvoker :
|
||||
{
|
||||
public:
|
||||
RemapInvoker(const Mat& _src, Mat& _dst, const Mat *_m1,
|
||||
const Mat *_m2, int _interpolation, int _borderType, const Scalar &_borderValue,
|
||||
const Mat *_m2, int _borderType, const Scalar &_borderValue,
|
||||
int _planar_input, RemapNNFunc _nnfunc, RemapFunc _ifunc, const void *_ctab) :
|
||||
ParallelLoopBody(), src(&_src), dst(&_dst), m1(_m1), m2(_m2),
|
||||
interpolation(_interpolation), borderType(_borderType), borderValue(_borderValue),
|
||||
borderType(_borderType), borderValue(_borderValue),
|
||||
planar_input(_planar_input), nnfunc(_nnfunc), ifunc(_ifunc), ctab(_ctab)
|
||||
{
|
||||
}
|
||||
@ -3077,7 +3077,7 @@ private:
|
||||
const Mat* src;
|
||||
Mat* dst;
|
||||
const Mat *m1, *m2;
|
||||
int interpolation, borderType;
|
||||
int borderType;
|
||||
Scalar borderValue;
|
||||
int planar_input;
|
||||
RemapNNFunc nnfunc;
|
||||
@ -3178,7 +3178,7 @@ void cv::remap( InputArray _src, OutputArray _dst,
|
||||
planar_input = map1.channels() == 1;
|
||||
}
|
||||
|
||||
RemapInvoker invoker(src, dst, m1, m2, interpolation,
|
||||
RemapInvoker invoker(src, dst, m1, m2,
|
||||
borderType, borderValue, planar_input, nnfunc, ifunc,
|
||||
ctab);
|
||||
parallel_for_(Range(0, dst.rows), invoker, dst.total()/(double)(1<<16));
|
||||
|
@ -40,21 +40,22 @@
|
||||
//M*/
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
// The function calculates center of gravity and the central second order moments
|
||||
static void icvCompleteMomentState( CvMoments* moments )
|
||||
static void completeMomentState( Moments* moments )
|
||||
{
|
||||
double cx = 0, cy = 0;
|
||||
double mu20, mu11, mu02;
|
||||
|
||||
assert( moments != 0 );
|
||||
moments->inv_sqrt_m00 = 0;
|
||||
|
||||
if( fabs(moments->m00) > DBL_EPSILON )
|
||||
{
|
||||
double inv_m00 = 1. / moments->m00;
|
||||
cx = moments->m10 * inv_m00;
|
||||
cy = moments->m01 * inv_m00;
|
||||
moments->inv_sqrt_m00 = std::sqrt( fabs(inv_m00) );
|
||||
}
|
||||
|
||||
// mu20 = m20 - m10*cx
|
||||
@ -80,115 +81,111 @@ static void icvCompleteMomentState( CvMoments* moments )
|
||||
}
|
||||
|
||||
|
||||
static void icvContourMoments( CvSeq* contour, CvMoments* moments )
|
||||
static Moments contourMoments( const Mat& contour )
|
||||
{
|
||||
int is_float = CV_SEQ_ELTYPE(contour) == CV_32FC2;
|
||||
Moments m;
|
||||
int lpt = contour.checkVector(2);
|
||||
int is_float = contour.depth() == CV_32F;
|
||||
const Point* ptsi = (const Point*)contour.data;
|
||||
const Point2f* ptsf = (const Point2f*)contour.data;
|
||||
|
||||
if( contour->total )
|
||||
CV_Assert( contour.depth() == CV_32S || contour.depth() == CV_32F );
|
||||
|
||||
if( lpt == 0 )
|
||||
return m;
|
||||
|
||||
double a00 = 0, a10 = 0, a01 = 0, a20 = 0, a11 = 0, a02 = 0, a30 = 0, a21 = 0, a12 = 0, a03 = 0;
|
||||
double xi, yi, xi2, yi2, xi_1, yi_1, xi_12, yi_12, dxy, xii_1, yii_1;
|
||||
|
||||
if( !is_float )
|
||||
{
|
||||
CvSeqReader reader;
|
||||
double a00, a10, a01, a20, a11, a02, a30, a21, a12, a03;
|
||||
double xi, yi, xi2, yi2, xi_1, yi_1, xi_12, yi_12, dxy, xii_1, yii_1;
|
||||
int lpt = contour->total;
|
||||
xi_1 = ptsi[lpt-1].x;
|
||||
yi_1 = ptsi[lpt-1].y;
|
||||
}
|
||||
else
|
||||
{
|
||||
xi_1 = ptsf[lpt-1].x;
|
||||
yi_1 = ptsf[lpt-1].y;
|
||||
}
|
||||
|
||||
a00 = a10 = a01 = a20 = a11 = a02 = a30 = a21 = a12 = a03 = 0;
|
||||
|
||||
cvStartReadSeq( contour, &reader, 0 );
|
||||
xi_12 = xi_1 * xi_1;
|
||||
yi_12 = yi_1 * yi_1;
|
||||
|
||||
for( int i = 0; i < lpt; i++ )
|
||||
{
|
||||
if( !is_float )
|
||||
{
|
||||
xi_1 = ((CvPoint*)(reader.ptr))->x;
|
||||
yi_1 = ((CvPoint*)(reader.ptr))->y;
|
||||
xi = ptsi[i].x;
|
||||
yi = ptsi[i].y;
|
||||
}
|
||||
else
|
||||
{
|
||||
xi_1 = ((CvPoint2D32f*)(reader.ptr))->x;
|
||||
yi_1 = ((CvPoint2D32f*)(reader.ptr))->y;
|
||||
}
|
||||
CV_NEXT_SEQ_ELEM( contour->elem_size, reader );
|
||||
|
||||
xi_12 = xi_1 * xi_1;
|
||||
yi_12 = yi_1 * yi_1;
|
||||
|
||||
while( lpt-- > 0 )
|
||||
{
|
||||
if( !is_float )
|
||||
{
|
||||
xi = ((CvPoint*)(reader.ptr))->x;
|
||||
yi = ((CvPoint*)(reader.ptr))->y;
|
||||
}
|
||||
else
|
||||
{
|
||||
xi = ((CvPoint2D32f*)(reader.ptr))->x;
|
||||
yi = ((CvPoint2D32f*)(reader.ptr))->y;
|
||||
}
|
||||
CV_NEXT_SEQ_ELEM( contour->elem_size, reader );
|
||||
|
||||
xi2 = xi * xi;
|
||||
yi2 = yi * yi;
|
||||
dxy = xi_1 * yi - xi * yi_1;
|
||||
xii_1 = xi_1 + xi;
|
||||
yii_1 = yi_1 + yi;
|
||||
|
||||
a00 += dxy;
|
||||
a10 += dxy * xii_1;
|
||||
a01 += dxy * yii_1;
|
||||
a20 += dxy * (xi_1 * xii_1 + xi2);
|
||||
a11 += dxy * (xi_1 * (yii_1 + yi_1) + xi * (yii_1 + yi));
|
||||
a02 += dxy * (yi_1 * yii_1 + yi2);
|
||||
a30 += dxy * xii_1 * (xi_12 + xi2);
|
||||
a03 += dxy * yii_1 * (yi_12 + yi2);
|
||||
a21 +=
|
||||
dxy * (xi_12 * (3 * yi_1 + yi) + 2 * xi * xi_1 * yii_1 +
|
||||
xi2 * (yi_1 + 3 * yi));
|
||||
a12 +=
|
||||
dxy * (yi_12 * (3 * xi_1 + xi) + 2 * yi * yi_1 * xii_1 +
|
||||
yi2 * (xi_1 + 3 * xi));
|
||||
|
||||
xi_1 = xi;
|
||||
yi_1 = yi;
|
||||
xi_12 = xi2;
|
||||
yi_12 = yi2;
|
||||
xi = ptsf[i].x;
|
||||
yi = ptsf[i].y;
|
||||
}
|
||||
|
||||
double db1_2, db1_6, db1_12, db1_24, db1_20, db1_60;
|
||||
xi2 = xi * xi;
|
||||
yi2 = yi * yi;
|
||||
dxy = xi_1 * yi - xi * yi_1;
|
||||
xii_1 = xi_1 + xi;
|
||||
yii_1 = yi_1 + yi;
|
||||
|
||||
if( fabs(a00) > FLT_EPSILON )
|
||||
{
|
||||
if( a00 > 0 )
|
||||
{
|
||||
db1_2 = 0.5;
|
||||
db1_6 = 0.16666666666666666666666666666667;
|
||||
db1_12 = 0.083333333333333333333333333333333;
|
||||
db1_24 = 0.041666666666666666666666666666667;
|
||||
db1_20 = 0.05;
|
||||
db1_60 = 0.016666666666666666666666666666667;
|
||||
}
|
||||
else
|
||||
{
|
||||
db1_2 = -0.5;
|
||||
db1_6 = -0.16666666666666666666666666666667;
|
||||
db1_12 = -0.083333333333333333333333333333333;
|
||||
db1_24 = -0.041666666666666666666666666666667;
|
||||
db1_20 = -0.05;
|
||||
db1_60 = -0.016666666666666666666666666666667;
|
||||
}
|
||||
|
||||
// spatial moments
|
||||
moments->m00 = a00 * db1_2;
|
||||
moments->m10 = a10 * db1_6;
|
||||
moments->m01 = a01 * db1_6;
|
||||
moments->m20 = a20 * db1_12;
|
||||
moments->m11 = a11 * db1_24;
|
||||
moments->m02 = a02 * db1_12;
|
||||
moments->m30 = a30 * db1_20;
|
||||
moments->m21 = a21 * db1_60;
|
||||
moments->m12 = a12 * db1_60;
|
||||
moments->m03 = a03 * db1_20;
|
||||
|
||||
icvCompleteMomentState( moments );
|
||||
}
|
||||
a00 += dxy;
|
||||
a10 += dxy * xii_1;
|
||||
a01 += dxy * yii_1;
|
||||
a20 += dxy * (xi_1 * xii_1 + xi2);
|
||||
a11 += dxy * (xi_1 * (yii_1 + yi_1) + xi * (yii_1 + yi));
|
||||
a02 += dxy * (yi_1 * yii_1 + yi2);
|
||||
a30 += dxy * xii_1 * (xi_12 + xi2);
|
||||
a03 += dxy * yii_1 * (yi_12 + yi2);
|
||||
a21 += dxy * (xi_12 * (3 * yi_1 + yi) + 2 * xi * xi_1 * yii_1 +
|
||||
xi2 * (yi_1 + 3 * yi));
|
||||
a12 += dxy * (yi_12 * (3 * xi_1 + xi) + 2 * yi * yi_1 * xii_1 +
|
||||
yi2 * (xi_1 + 3 * xi));
|
||||
xi_1 = xi;
|
||||
yi_1 = yi;
|
||||
xi_12 = xi2;
|
||||
yi_12 = yi2;
|
||||
}
|
||||
|
||||
if( fabs(a00) > FLT_EPSILON )
|
||||
{
|
||||
double db1_2, db1_6, db1_12, db1_24, db1_20, db1_60;
|
||||
|
||||
if( a00 > 0 )
|
||||
{
|
||||
db1_2 = 0.5;
|
||||
db1_6 = 0.16666666666666666666666666666667;
|
||||
db1_12 = 0.083333333333333333333333333333333;
|
||||
db1_24 = 0.041666666666666666666666666666667;
|
||||
db1_20 = 0.05;
|
||||
db1_60 = 0.016666666666666666666666666666667;
|
||||
}
|
||||
else
|
||||
{
|
||||
db1_2 = -0.5;
|
||||
db1_6 = -0.16666666666666666666666666666667;
|
||||
db1_12 = -0.083333333333333333333333333333333;
|
||||
db1_24 = -0.041666666666666666666666666666667;
|
||||
db1_20 = -0.05;
|
||||
db1_60 = -0.016666666666666666666666666666667;
|
||||
}
|
||||
|
||||
// spatial moments
|
||||
m.m00 = a00 * db1_2;
|
||||
m.m10 = a10 * db1_6;
|
||||
m.m01 = a01 * db1_6;
|
||||
m.m20 = a20 * db1_12;
|
||||
m.m11 = a11 * db1_24;
|
||||
m.m02 = a02 * db1_12;
|
||||
m.m30 = a30 * db1_20;
|
||||
m.m21 = a21 * db1_60;
|
||||
m.m12 = a12 * db1_60;
|
||||
m.m03 = a03 * db1_20;
|
||||
|
||||
completeMomentState( &m );
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
@ -197,9 +194,9 @@ static void icvContourMoments( CvSeq* contour, CvMoments* moments )
|
||||
\****************************************************************************************/
|
||||
|
||||
template<typename T, typename WT, typename MT>
|
||||
static void momentsInTile( const cv::Mat& img, double* moments )
|
||||
static void momentsInTile( const Mat& img, double* moments )
|
||||
{
|
||||
cv::Size size = img.size();
|
||||
Size size = img.size();
|
||||
int x, y;
|
||||
MT mom[10] = {0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
@ -247,10 +244,10 @@ template<> void momentsInTile<uchar, int, int>( const cv::Mat& img, double* mome
|
||||
typedef uchar T;
|
||||
typedef int WT;
|
||||
typedef int MT;
|
||||
cv::Size size = img.size();
|
||||
Size size = img.size();
|
||||
int y;
|
||||
MT mom[10] = {0,0,0,0,0,0,0,0,0,0};
|
||||
bool useSIMD = cv::checkHardwareSupport(CV_CPU_SSE2);
|
||||
bool useSIMD = checkHardwareSupport(CV_CPU_SSE2);
|
||||
|
||||
for( y = 0; y < size.height; y++ )
|
||||
{
|
||||
@ -318,233 +315,7 @@ template<> void momentsInTile<uchar, int, int>( const cv::Mat& img, double* mome
|
||||
|
||||
#endif
|
||||
|
||||
typedef void (*CvMomentsInTileFunc)(const cv::Mat& img, double* moments);
|
||||
|
||||
CV_IMPL void cvMoments( const void* array, CvMoments* moments, int binary )
|
||||
{
|
||||
const int TILE_SIZE = 32;
|
||||
int type, depth, cn, coi = 0;
|
||||
CvMat stub, *mat = (CvMat*)array;
|
||||
CvMomentsInTileFunc func = 0;
|
||||
CvContour contourHeader;
|
||||
CvSeq* contour = 0;
|
||||
CvSeqBlock block;
|
||||
double buf[TILE_SIZE*TILE_SIZE];
|
||||
uchar nzbuf[TILE_SIZE*TILE_SIZE];
|
||||
|
||||
if( CV_IS_SEQ( array ))
|
||||
{
|
||||
contour = (CvSeq*)array;
|
||||
if( !CV_IS_SEQ_POINT_SET( contour ))
|
||||
CV_Error( CV_StsBadArg, "The passed sequence is not a valid contour" );
|
||||
}
|
||||
|
||||
if( !moments )
|
||||
CV_Error( CV_StsNullPtr, "" );
|
||||
|
||||
memset( moments, 0, sizeof(*moments));
|
||||
|
||||
if( !contour )
|
||||
{
|
||||
mat = cvGetMat( mat, &stub, &coi );
|
||||
type = CV_MAT_TYPE( mat->type );
|
||||
|
||||
if( type == CV_32SC2 || type == CV_32FC2 )
|
||||
{
|
||||
contour = cvPointSeqFromMat(
|
||||
CV_SEQ_KIND_CURVE | CV_SEQ_FLAG_CLOSED,
|
||||
mat, &contourHeader, &block );
|
||||
}
|
||||
}
|
||||
|
||||
if( contour )
|
||||
{
|
||||
icvContourMoments( contour, moments );
|
||||
return;
|
||||
}
|
||||
|
||||
type = CV_MAT_TYPE( mat->type );
|
||||
depth = CV_MAT_DEPTH( type );
|
||||
cn = CV_MAT_CN( type );
|
||||
|
||||
cv::Size size = cvGetMatSize( mat );
|
||||
|
||||
if( cn > 1 && coi == 0 )
|
||||
CV_Error( CV_StsBadArg, "Invalid image type" );
|
||||
|
||||
if( size.width <= 0 || size.height <= 0 )
|
||||
return;
|
||||
|
||||
if( binary || depth == CV_8U )
|
||||
func = momentsInTile<uchar, int, int>;
|
||||
else if( depth == CV_16U )
|
||||
func = momentsInTile<ushort, int, int64>;
|
||||
else if( depth == CV_16S )
|
||||
func = momentsInTile<short, int, int64>;
|
||||
else if( depth == CV_32F )
|
||||
func = momentsInTile<float, double, double>;
|
||||
else if( depth == CV_64F )
|
||||
func = momentsInTile<double, double, double>;
|
||||
else
|
||||
CV_Error( CV_StsUnsupportedFormat, "" );
|
||||
|
||||
cv::Mat src0(mat);
|
||||
|
||||
for( int y = 0; y < size.height; y += TILE_SIZE )
|
||||
{
|
||||
cv::Size tileSize;
|
||||
tileSize.height = std::min(TILE_SIZE, size.height - y);
|
||||
|
||||
for( int x = 0; x < size.width; x += TILE_SIZE )
|
||||
{
|
||||
tileSize.width = std::min(TILE_SIZE, size.width - x);
|
||||
cv::Mat src(src0, cv::Rect(x, y, tileSize.width, tileSize.height));
|
||||
|
||||
if( coi > 0 )
|
||||
{
|
||||
cv::Mat tmp(tileSize, depth, buf);
|
||||
int pairs[] = {coi-1, 0};
|
||||
cv::mixChannels(&src, 1, &tmp, 1, pairs, 1);
|
||||
src = tmp;
|
||||
}
|
||||
if( binary )
|
||||
{
|
||||
cv::Mat tmp(tileSize, CV_8U, nzbuf);
|
||||
cv::compare( src, 0, tmp, CV_CMP_NE );
|
||||
src = tmp;
|
||||
}
|
||||
|
||||
double mom[10];
|
||||
func( src, mom );
|
||||
|
||||
if(binary)
|
||||
{
|
||||
double s = 1./255;
|
||||
for( int k = 0; k < 10; k++ )
|
||||
mom[k] *= s;
|
||||
}
|
||||
|
||||
double xm = x * mom[0], ym = y * mom[0];
|
||||
|
||||
// accumulate moments computed in each tile
|
||||
|
||||
// + m00 ( = m00' )
|
||||
moments->m00 += mom[0];
|
||||
|
||||
// + m10 ( = m10' + x*m00' )
|
||||
moments->m10 += mom[1] + xm;
|
||||
|
||||
// + m01 ( = m01' + y*m00' )
|
||||
moments->m01 += mom[2] + ym;
|
||||
|
||||
// + m20 ( = m20' + 2*x*m10' + x*x*m00' )
|
||||
moments->m20 += mom[3] + x * (mom[1] * 2 + xm);
|
||||
|
||||
// + m11 ( = m11' + x*m01' + y*m10' + x*y*m00' )
|
||||
moments->m11 += mom[4] + x * (mom[2] + ym) + y * mom[1];
|
||||
|
||||
// + m02 ( = m02' + 2*y*m01' + y*y*m00' )
|
||||
moments->m02 += mom[5] + y * (mom[2] * 2 + ym);
|
||||
|
||||
// + m30 ( = m30' + 3*x*m20' + 3*x*x*m10' + x*x*x*m00' )
|
||||
moments->m30 += mom[6] + x * (3. * mom[3] + x * (3. * mom[1] + xm));
|
||||
|
||||
// + m21 ( = m21' + x*(2*m11' + 2*y*m10' + x*m01' + x*y*m00') + y*m20')
|
||||
moments->m21 += mom[7] + x * (2 * (mom[4] + y * mom[1]) + x * (mom[2] + ym)) + y * mom[3];
|
||||
|
||||
// + m12 ( = m12' + y*(2*m11' + 2*x*m01' + y*m10' + x*y*m00') + x*m02')
|
||||
moments->m12 += mom[8] + y * (2 * (mom[4] + x * mom[2]) + y * (mom[1] + xm)) + x * mom[5];
|
||||
|
||||
// + m03 ( = m03' + 3*y*m02' + 3*y*y*m01' + y*y*y*m00' )
|
||||
moments->m03 += mom[9] + y * (3. * mom[5] + y * (3. * mom[2] + ym));
|
||||
}
|
||||
}
|
||||
|
||||
icvCompleteMomentState( moments );
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL void cvGetHuMoments( CvMoments * mState, CvHuMoments * HuState )
|
||||
{
|
||||
if( !mState || !HuState )
|
||||
CV_Error( CV_StsNullPtr, "" );
|
||||
|
||||
double m00s = mState->inv_sqrt_m00, m00 = m00s * m00s, s2 = m00 * m00, s3 = s2 * m00s;
|
||||
|
||||
double nu20 = mState->mu20 * s2,
|
||||
nu11 = mState->mu11 * s2,
|
||||
nu02 = mState->mu02 * s2,
|
||||
nu30 = mState->mu30 * s3,
|
||||
nu21 = mState->mu21 * s3, nu12 = mState->mu12 * s3, nu03 = mState->mu03 * s3;
|
||||
|
||||
double t0 = nu30 + nu12;
|
||||
double t1 = nu21 + nu03;
|
||||
|
||||
double q0 = t0 * t0, q1 = t1 * t1;
|
||||
|
||||
double n4 = 4 * nu11;
|
||||
double s = nu20 + nu02;
|
||||
double d = nu20 - nu02;
|
||||
|
||||
HuState->hu1 = s;
|
||||
HuState->hu2 = d * d + n4 * nu11;
|
||||
HuState->hu4 = q0 + q1;
|
||||
HuState->hu6 = d * (q0 - q1) + n4 * t0 * t1;
|
||||
|
||||
t0 *= q0 - 3 * q1;
|
||||
t1 *= 3 * q0 - q1;
|
||||
|
||||
q0 = nu30 - 3 * nu12;
|
||||
q1 = 3 * nu21 - nu03;
|
||||
|
||||
HuState->hu3 = q0 * q0 + q1 * q1;
|
||||
HuState->hu5 = q0 * t0 + q1 * t1;
|
||||
HuState->hu7 = q1 * t0 - q0 * t1;
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL double cvGetSpatialMoment( CvMoments * moments, int x_order, int y_order )
|
||||
{
|
||||
int order = x_order + y_order;
|
||||
|
||||
if( !moments )
|
||||
CV_Error( CV_StsNullPtr, "" );
|
||||
if( (x_order | y_order) < 0 || order > 3 )
|
||||
CV_Error( CV_StsOutOfRange, "" );
|
||||
|
||||
return (&(moments->m00))[order + (order >> 1) + (order > 2) * 2 + y_order];
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL double cvGetCentralMoment( CvMoments * moments, int x_order, int y_order )
|
||||
{
|
||||
int order = x_order + y_order;
|
||||
|
||||
if( !moments )
|
||||
CV_Error( CV_StsNullPtr, "" );
|
||||
if( (x_order | y_order) < 0 || order > 3 )
|
||||
CV_Error( CV_StsOutOfRange, "" );
|
||||
|
||||
return order >= 2 ? (&(moments->m00))[4 + order * 3 + y_order] :
|
||||
order == 0 ? moments->m00 : 0;
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL double cvGetNormalizedCentralMoment( CvMoments * moments, int x_order, int y_order )
|
||||
{
|
||||
int order = x_order + y_order;
|
||||
|
||||
double mu = cvGetCentralMoment( moments, x_order, y_order );
|
||||
double m00s = moments->inv_sqrt_m00;
|
||||
|
||||
while( --order >= 0 )
|
||||
mu *= m00s;
|
||||
return mu * m00s * m00s;
|
||||
}
|
||||
|
||||
|
||||
namespace cv
|
||||
{
|
||||
typedef void (*MomentsInTileFunc)(const Mat& img, double* moments);
|
||||
|
||||
Moments::Moments()
|
||||
{
|
||||
@ -604,15 +375,112 @@ Moments::operator CvMoments() const
|
||||
|
||||
}
|
||||
|
||||
cv::Moments cv::moments( InputArray _array, bool binaryImage )
|
||||
|
||||
cv::Moments cv::moments( InputArray _src, bool binary )
|
||||
{
|
||||
CvMoments om;
|
||||
Mat arr = _array.getMat();
|
||||
CvMat c_array = arr;
|
||||
cvMoments(&c_array, &om, binaryImage);
|
||||
return om;
|
||||
const int TILE_SIZE = 32;
|
||||
Mat mat = _src.getMat();
|
||||
MomentsInTileFunc func = 0;
|
||||
uchar nzbuf[TILE_SIZE*TILE_SIZE];
|
||||
Moments m;
|
||||
int type = mat.type();
|
||||
int depth = CV_MAT_DEPTH( type );
|
||||
int cn = CV_MAT_CN( type );
|
||||
|
||||
if( mat.checkVector(2) >= 0 && (depth == CV_32F || depth == CV_32S))
|
||||
return contourMoments(mat);
|
||||
|
||||
Size size = mat.size();
|
||||
|
||||
if( cn > 1 )
|
||||
CV_Error( CV_StsBadArg, "Invalid image type" );
|
||||
|
||||
if( size.width <= 0 || size.height <= 0 )
|
||||
return m;
|
||||
|
||||
if( binary || depth == CV_8U )
|
||||
func = momentsInTile<uchar, int, int>;
|
||||
else if( depth == CV_16U )
|
||||
func = momentsInTile<ushort, int, int64>;
|
||||
else if( depth == CV_16S )
|
||||
func = momentsInTile<short, int, int64>;
|
||||
else if( depth == CV_32F )
|
||||
func = momentsInTile<float, double, double>;
|
||||
else if( depth == CV_64F )
|
||||
func = momentsInTile<double, double, double>;
|
||||
else
|
||||
CV_Error( CV_StsUnsupportedFormat, "" );
|
||||
|
||||
Mat src0(mat);
|
||||
|
||||
for( int y = 0; y < size.height; y += TILE_SIZE )
|
||||
{
|
||||
Size tileSize;
|
||||
tileSize.height = std::min(TILE_SIZE, size.height - y);
|
||||
|
||||
for( int x = 0; x < size.width; x += TILE_SIZE )
|
||||
{
|
||||
tileSize.width = std::min(TILE_SIZE, size.width - x);
|
||||
Mat src(src0, cv::Rect(x, y, tileSize.width, tileSize.height));
|
||||
|
||||
if( binary )
|
||||
{
|
||||
cv::Mat tmp(tileSize, CV_8U, nzbuf);
|
||||
cv::compare( src, 0, tmp, CV_CMP_NE );
|
||||
src = tmp;
|
||||
}
|
||||
|
||||
double mom[10];
|
||||
func( src, mom );
|
||||
|
||||
if(binary)
|
||||
{
|
||||
double s = 1./255;
|
||||
for( int k = 0; k < 10; k++ )
|
||||
mom[k] *= s;
|
||||
}
|
||||
|
||||
double xm = x * mom[0], ym = y * mom[0];
|
||||
|
||||
// accumulate moments computed in each tile
|
||||
|
||||
// + m00 ( = m00' )
|
||||
m.m00 += mom[0];
|
||||
|
||||
// + m10 ( = m10' + x*m00' )
|
||||
m.m10 += mom[1] + xm;
|
||||
|
||||
// + m01 ( = m01' + y*m00' )
|
||||
m.m01 += mom[2] + ym;
|
||||
|
||||
// + m20 ( = m20' + 2*x*m10' + x*x*m00' )
|
||||
m.m20 += mom[3] + x * (mom[1] * 2 + xm);
|
||||
|
||||
// + m11 ( = m11' + x*m01' + y*m10' + x*y*m00' )
|
||||
m.m11 += mom[4] + x * (mom[2] + ym) + y * mom[1];
|
||||
|
||||
// + m02 ( = m02' + 2*y*m01' + y*y*m00' )
|
||||
m.m02 += mom[5] + y * (mom[2] * 2 + ym);
|
||||
|
||||
// + m30 ( = m30' + 3*x*m20' + 3*x*x*m10' + x*x*x*m00' )
|
||||
m.m30 += mom[6] + x * (3. * mom[3] + x * (3. * mom[1] + xm));
|
||||
|
||||
// + m21 ( = m21' + x*(2*m11' + 2*y*m10' + x*m01' + x*y*m00') + y*m20')
|
||||
m.m21 += mom[7] + x * (2 * (mom[4] + y * mom[1]) + x * (mom[2] + ym)) + y * mom[3];
|
||||
|
||||
// + m12 ( = m12' + y*(2*m11' + 2*x*m01' + y*m10' + x*y*m00') + x*m02')
|
||||
m.m12 += mom[8] + y * (2 * (mom[4] + x * mom[2]) + y * (mom[1] + xm)) + x * mom[5];
|
||||
|
||||
// + m03 ( = m03' + 3*y*m02' + 3*y*y*m01' + y*y*y*m00' )
|
||||
m.m03 += mom[9] + y * (3. * mom[5] + y * (3. * mom[2] + ym));
|
||||
}
|
||||
}
|
||||
|
||||
completeMomentState( &m );
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
void cv::HuMoments( const Moments& m, double hu[7] )
|
||||
{
|
||||
double t0 = m.nu30 + m.nu12;
|
||||
@ -648,4 +516,98 @@ void cv::HuMoments( const Moments& m, OutputArray _hu )
|
||||
HuMoments(m, (double*)hu.data);
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL void cvMoments( const CvArr* arr, CvMoments* moments, int binary )
|
||||
{
|
||||
const IplImage* img = (const IplImage*)arr;
|
||||
cv::Mat src;
|
||||
if( CV_IS_IMAGE(arr) && img->roi && img->roi->coi > 0 )
|
||||
cv::extractImageCOI(arr, src, img->roi->coi-1);
|
||||
else
|
||||
src = cv::cvarrToMat(arr);
|
||||
cv::Moments m = cv::moments(src, binary != 0);
|
||||
CV_Assert( moments != 0 );
|
||||
*moments = m;
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL double cvGetSpatialMoment( CvMoments * moments, int x_order, int y_order )
|
||||
{
|
||||
int order = x_order + y_order;
|
||||
|
||||
if( !moments )
|
||||
CV_Error( CV_StsNullPtr, "" );
|
||||
if( (x_order | y_order) < 0 || order > 3 )
|
||||
CV_Error( CV_StsOutOfRange, "" );
|
||||
|
||||
return (&(moments->m00))[order + (order >> 1) + (order > 2) * 2 + y_order];
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL double cvGetCentralMoment( CvMoments * moments, int x_order, int y_order )
|
||||
{
|
||||
int order = x_order + y_order;
|
||||
|
||||
if( !moments )
|
||||
CV_Error( CV_StsNullPtr, "" );
|
||||
if( (x_order | y_order) < 0 || order > 3 )
|
||||
CV_Error( CV_StsOutOfRange, "" );
|
||||
|
||||
return order >= 2 ? (&(moments->m00))[4 + order * 3 + y_order] :
|
||||
order == 0 ? moments->m00 : 0;
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL double cvGetNormalizedCentralMoment( CvMoments * moments, int x_order, int y_order )
|
||||
{
|
||||
int order = x_order + y_order;
|
||||
|
||||
double mu = cvGetCentralMoment( moments, x_order, y_order );
|
||||
double m00s = moments->inv_sqrt_m00;
|
||||
|
||||
while( --order >= 0 )
|
||||
mu *= m00s;
|
||||
return mu * m00s * m00s;
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL void cvGetHuMoments( CvMoments * mState, CvHuMoments * HuState )
|
||||
{
|
||||
if( !mState || !HuState )
|
||||
CV_Error( CV_StsNullPtr, "" );
|
||||
|
||||
double m00s = mState->inv_sqrt_m00, m00 = m00s * m00s, s2 = m00 * m00, s3 = s2 * m00s;
|
||||
|
||||
double nu20 = mState->mu20 * s2,
|
||||
nu11 = mState->mu11 * s2,
|
||||
nu02 = mState->mu02 * s2,
|
||||
nu30 = mState->mu30 * s3,
|
||||
nu21 = mState->mu21 * s3, nu12 = mState->mu12 * s3, nu03 = mState->mu03 * s3;
|
||||
|
||||
double t0 = nu30 + nu12;
|
||||
double t1 = nu21 + nu03;
|
||||
|
||||
double q0 = t0 * t0, q1 = t1 * t1;
|
||||
|
||||
double n4 = 4 * nu11;
|
||||
double s = nu20 + nu02;
|
||||
double d = nu20 - nu02;
|
||||
|
||||
HuState->hu1 = s;
|
||||
HuState->hu2 = d * d + n4 * nu11;
|
||||
HuState->hu4 = q0 + q1;
|
||||
HuState->hu6 = d * (q0 - q1) + n4 * t0 * t1;
|
||||
|
||||
t0 *= q0 - 3 * q1;
|
||||
t1 *= 3 * q0 - q1;
|
||||
|
||||
q0 = nu30 - 3 * nu12;
|
||||
q1 = 3 * nu21 - nu03;
|
||||
|
||||
HuState->hu3 = q0 * q0 + q1 * q1;
|
||||
HuState->hu5 = q0 * t0 + q1 * t1;
|
||||
HuState->hu7 = q1 * t0 - q0 * t1;
|
||||
}
|
||||
|
||||
|
||||
/* End of file. */
|
||||
|
@ -116,41 +116,12 @@ CvPyramid;
|
||||
#define CV_SET( dst, val, len, idx ) \
|
||||
for( (idx) = 0; (idx) < (len); (idx)++) (dst)[idx] = (val)
|
||||
|
||||
/* performs convolution of 2d floating-point array with 3x1, 1x3 or separable 3x3 mask */
|
||||
void icvSepConvSmall3_32f( float* src, int src_step, float* dst, int dst_step,
|
||||
CvSize src_size, const float* kx, const float* ky, float* buffer );
|
||||
|
||||
#undef CV_CALC_MIN
|
||||
#define CV_CALC_MIN(a, b) if((a) > (b)) (a) = (b)
|
||||
|
||||
#undef CV_CALC_MAX
|
||||
#define CV_CALC_MAX(a, b) if((a) < (b)) (a) = (b)
|
||||
|
||||
CvStatus CV_STDCALL
|
||||
icvCopyReplicateBorder_8u( const uchar* src, int srcstep, CvSize srcroi,
|
||||
uchar* dst, int dststep, CvSize dstroi,
|
||||
int left, int right, int cn, const uchar* value = 0 );
|
||||
|
||||
CvStatus CV_STDCALL icvGetRectSubPix_8u_C1R
|
||||
( const uchar* src, int src_step, CvSize src_size,
|
||||
uchar* dst, int dst_step, CvSize win_size, CvPoint2D32f center );
|
||||
CvStatus CV_STDCALL icvGetRectSubPix_8u32f_C1R
|
||||
( const uchar* src, int src_step, CvSize src_size,
|
||||
float* dst, int dst_step, CvSize win_size, CvPoint2D32f center );
|
||||
CvStatus CV_STDCALL icvGetRectSubPix_32f_C1R
|
||||
( const float* src, int src_step, CvSize src_size,
|
||||
float* dst, int dst_step, CvSize win_size, CvPoint2D32f center );
|
||||
|
||||
CvStatus CV_STDCALL icvGetQuadrangleSubPix_8u_C1R
|
||||
( const uchar* src, int src_step, CvSize src_size,
|
||||
uchar* dst, int dst_step, CvSize win_size, const float *matrix );
|
||||
CvStatus CV_STDCALL icvGetQuadrangleSubPix_8u32f_C1R
|
||||
( const uchar* src, int src_step, CvSize src_size,
|
||||
float* dst, int dst_step, CvSize win_size, const float *matrix );
|
||||
CvStatus CV_STDCALL icvGetQuadrangleSubPix_32f_C1R
|
||||
( const float* src, int src_step, CvSize src_size,
|
||||
float* dst, int dst_step, CvSize win_size, const float *matrix );
|
||||
|
||||
#include "_geom.h"
|
||||
|
||||
#endif /*__OPENCV_CV_INTERNAL_H_*/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,10 +7,11 @@
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -23,7 +24,7 @@
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// * 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
|
||||
@ -45,56 +46,59 @@
|
||||
* Watershed *
|
||||
\****************************************************************************************/
|
||||
|
||||
typedef struct CvWSNode
|
||||
namespace cv
|
||||
{
|
||||
struct CvWSNode* next;
|
||||
|
||||
struct WSNode
|
||||
{
|
||||
int next;
|
||||
int mask_ofs;
|
||||
int img_ofs;
|
||||
}
|
||||
CvWSNode;
|
||||
};
|
||||
|
||||
typedef struct CvWSQueue
|
||||
struct WSQueue
|
||||
{
|
||||
CvWSNode* first;
|
||||
CvWSNode* last;
|
||||
}
|
||||
CvWSQueue;
|
||||
WSQueue() { first = last = 0; }
|
||||
int first, last;
|
||||
};
|
||||
|
||||
static CvWSNode*
|
||||
icvAllocWSNodes( CvMemStorage* storage )
|
||||
|
||||
static int
|
||||
allocWSNodes( vector<WSNode>& storage )
|
||||
{
|
||||
CvWSNode* n = 0;
|
||||
int sz = (int)storage.size();
|
||||
int newsz = MAX(128, sz*3/2);
|
||||
|
||||
int i, count = (storage->block_size - sizeof(CvMemBlock))/sizeof(*n) - 1;
|
||||
storage.resize(newsz);
|
||||
if( sz == 0 )
|
||||
{
|
||||
storage[0].next = 0;
|
||||
sz = 1;
|
||||
}
|
||||
for( int i = sz; i < newsz-1; i++ )
|
||||
storage[i].next = i+1;
|
||||
storage[newsz-1].next = 0;
|
||||
return sz;
|
||||
}
|
||||
|
||||
n = (CvWSNode*)cvMemStorageAlloc( storage, count*sizeof(*n) );
|
||||
for( i = 0; i < count-1; i++ )
|
||||
n[i].next = n + i + 1;
|
||||
n[count-1].next = 0;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL void
|
||||
cvWatershed( const CvArr* srcarr, CvArr* dstarr )
|
||||
void cv::watershed( InputArray _src, InputOutputArray _markers )
|
||||
{
|
||||
const int IN_QUEUE = -2;
|
||||
const int WSHED = -1;
|
||||
const int NQ = 256;
|
||||
cv::Ptr<CvMemStorage> storage;
|
||||
|
||||
CvMat sstub, *src;
|
||||
CvMat dstub, *dst;
|
||||
CvSize size;
|
||||
CvWSNode* free_node = 0, *node;
|
||||
CvWSQueue q[NQ];
|
||||
Mat src = _src.getMat(), dst = _markers.getMat();
|
||||
Size size = src.size();
|
||||
|
||||
vector<WSNode> storage;
|
||||
int free_node = 0, node;
|
||||
WSQueue q[NQ];
|
||||
int active_queue;
|
||||
int i, j;
|
||||
int db, dg, dr;
|
||||
int* mask;
|
||||
uchar* img;
|
||||
int mstep, istep;
|
||||
int subs_tab[513];
|
||||
|
||||
// MAX(a,b) = b + MAX(a-b,0)
|
||||
@ -102,66 +106,51 @@ cvWatershed( const CvArr* srcarr, CvArr* dstarr )
|
||||
// MIN(a,b) = a - MAX(a-b,0)
|
||||
#define ws_min(a,b) ((a) - subs_tab[(a)-(b)+NQ])
|
||||
|
||||
#define ws_push(idx,mofs,iofs) \
|
||||
{ \
|
||||
if( !free_node ) \
|
||||
free_node = icvAllocWSNodes( storage );\
|
||||
node = free_node; \
|
||||
free_node = free_node->next;\
|
||||
node->next = 0; \
|
||||
node->mask_ofs = mofs; \
|
||||
node->img_ofs = iofs; \
|
||||
if( q[idx].last ) \
|
||||
q[idx].last->next=node; \
|
||||
else \
|
||||
q[idx].first = node; \
|
||||
q[idx].last = node; \
|
||||
#define ws_push(idx,mofs,iofs) \
|
||||
{ \
|
||||
if( !free_node ) \
|
||||
free_node = allocWSNodes( storage );\
|
||||
node = free_node; \
|
||||
free_node = storage[free_node].next;\
|
||||
storage[node].next = 0; \
|
||||
storage[node].mask_ofs = mofs; \
|
||||
storage[node].img_ofs = iofs; \
|
||||
if( q[idx].last ) \
|
||||
storage[q[idx].last].next=node; \
|
||||
else \
|
||||
q[idx].first = node; \
|
||||
q[idx].last = node; \
|
||||
}
|
||||
|
||||
#define ws_pop(idx,mofs,iofs) \
|
||||
{ \
|
||||
node = q[idx].first; \
|
||||
q[idx].first = node->next; \
|
||||
if( !node->next ) \
|
||||
q[idx].last = 0; \
|
||||
node->next = free_node; \
|
||||
free_node = node; \
|
||||
mofs = node->mask_ofs; \
|
||||
iofs = node->img_ofs; \
|
||||
#define ws_pop(idx,mofs,iofs) \
|
||||
{ \
|
||||
node = q[idx].first; \
|
||||
q[idx].first = storage[node].next; \
|
||||
if( !storage[node].next ) \
|
||||
q[idx].last = 0; \
|
||||
storage[node].next = free_node; \
|
||||
free_node = node; \
|
||||
mofs = storage[node].mask_ofs; \
|
||||
iofs = storage[node].img_ofs; \
|
||||
}
|
||||
|
||||
#define c_diff(ptr1,ptr2,diff) \
|
||||
{ \
|
||||
db = abs((ptr1)[0] - (ptr2)[0]);\
|
||||
dg = abs((ptr1)[1] - (ptr2)[1]);\
|
||||
dr = abs((ptr1)[2] - (ptr2)[2]);\
|
||||
diff = ws_max(db,dg); \
|
||||
diff = ws_max(diff,dr); \
|
||||
assert( 0 <= diff && diff <= 255 ); \
|
||||
#define c_diff(ptr1,ptr2,diff) \
|
||||
{ \
|
||||
db = std::abs((ptr1)[0] - (ptr2)[0]);\
|
||||
dg = std::abs((ptr1)[1] - (ptr2)[1]);\
|
||||
dr = std::abs((ptr1)[2] - (ptr2)[2]);\
|
||||
diff = ws_max(db,dg); \
|
||||
diff = ws_max(diff,dr); \
|
||||
assert( 0 <= diff && diff <= 255 ); \
|
||||
}
|
||||
|
||||
src = cvGetMat( srcarr, &sstub );
|
||||
dst = cvGetMat( dstarr, &dstub );
|
||||
CV_Assert( src.type() == CV_8UC3 && dst.type() == CV_32SC1 );
|
||||
CV_Assert( src.size() == dst.size() );
|
||||
|
||||
if( CV_MAT_TYPE(src->type) != CV_8UC3 )
|
||||
CV_Error( CV_StsUnsupportedFormat, "Only 8-bit, 3-channel input images are supported" );
|
||||
|
||||
if( CV_MAT_TYPE(dst->type) != CV_32SC1 )
|
||||
CV_Error( CV_StsUnsupportedFormat,
|
||||
"Only 32-bit, 1-channel output images are supported" );
|
||||
|
||||
if( !CV_ARE_SIZES_EQ( src, dst ))
|
||||
CV_Error( CV_StsUnmatchedSizes, "The input and output images must have the same size" );
|
||||
|
||||
size = cvGetMatSize(src);
|
||||
storage = cvCreateMemStorage();
|
||||
|
||||
istep = src->step;
|
||||
img = src->data.ptr;
|
||||
mstep = dst->step / sizeof(mask[0]);
|
||||
mask = dst->data.i;
|
||||
|
||||
memset( q, 0, NQ*sizeof(q[0]) );
|
||||
const uchar* img = src.data;
|
||||
int istep = src.step/sizeof(img[0]);
|
||||
int* mask = dst.ptr<int>();
|
||||
int mstep = dst.step / sizeof(mask[0]);
|
||||
|
||||
for( i = 0; i < 256; i++ )
|
||||
subs_tab[i] = 0;
|
||||
@ -185,7 +174,7 @@ cvWatershed( const CvArr* srcarr, CvArr* dstarr )
|
||||
if( m[0] < 0 ) m[0] = 0;
|
||||
if( m[0] == 0 && (m[-1] > 0 || m[1] > 0 || m[-mstep] > 0 || m[mstep] > 0) )
|
||||
{
|
||||
uchar* ptr = img + j*3;
|
||||
const uchar* ptr = img + j*3;
|
||||
int idx = 256, t;
|
||||
if( m[-1] > 0 )
|
||||
c_diff( ptr, ptr - 3, idx );
|
||||
@ -221,8 +210,8 @@ cvWatershed( const CvArr* srcarr, CvArr* dstarr )
|
||||
return;
|
||||
|
||||
active_queue = i;
|
||||
img = src->data.ptr;
|
||||
mask = dst->data.i;
|
||||
img = src.data;
|
||||
mask = dst.ptr<int>();
|
||||
|
||||
// recursively fill the basins
|
||||
for(;;)
|
||||
@ -230,7 +219,7 @@ cvWatershed( const CvArr* srcarr, CvArr* dstarr )
|
||||
int mofs, iofs;
|
||||
int lab = 0, t;
|
||||
int* m;
|
||||
uchar* ptr;
|
||||
const uchar* ptr;
|
||||
|
||||
if( q[active_queue].first == 0 )
|
||||
{
|
||||
@ -303,23 +292,23 @@ cvWatershed( const CvArr* srcarr, CvArr* dstarr )
|
||||
}
|
||||
|
||||
|
||||
void cv::watershed( InputArray _src, InputOutputArray markers )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
CvMat c_src = _src.getMat(), c_markers = markers.getMat();
|
||||
cvWatershed( &c_src, &c_markers );
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
* Meanshift *
|
||||
\****************************************************************************************/
|
||||
|
||||
CV_IMPL void
|
||||
cvPyrMeanShiftFiltering( const CvArr* srcarr, CvArr* dstarr,
|
||||
double sp0, double sr, int max_level,
|
||||
CvTermCriteria termcrit )
|
||||
|
||||
void cv::pyrMeanShiftFiltering( InputArray _src, OutputArray _dst,
|
||||
double sp0, double sr, int max_level,
|
||||
TermCriteria termcrit )
|
||||
{
|
||||
Mat src0 = _src.getMat();
|
||||
|
||||
if( src0.empty() )
|
||||
return;
|
||||
|
||||
_dst.create( src0.size(), src0.type() );
|
||||
Mat dst0 = _dst.getMat();
|
||||
|
||||
const int cn = 3;
|
||||
const int MAX_LEVELS = 8;
|
||||
|
||||
@ -338,8 +327,7 @@ cvPyrMeanShiftFiltering( const CvArr* srcarr, CvArr* dstarr,
|
||||
double sr2 = sr * sr;
|
||||
int isr2 = cvRound(sr2), isr22 = MAX(isr2,16);
|
||||
int tab[768];
|
||||
cv::Mat src0 = cv::cvarrToMat(srcarr);
|
||||
cv::Mat dst0 = cv::cvarrToMat(dstarr);
|
||||
|
||||
|
||||
if( src0.type() != CV_8UC3 )
|
||||
CV_Error( CV_StsUnsupportedFormat, "Only 8-bit, 3-channel images are supported" );
|
||||
@ -351,9 +339,9 @@ cvPyrMeanShiftFiltering( const CvArr* srcarr, CvArr* dstarr,
|
||||
CV_Error( CV_StsUnmatchedSizes, "The input and output images must have the same size" );
|
||||
|
||||
if( !(termcrit.type & CV_TERMCRIT_ITER) )
|
||||
termcrit.max_iter = 5;
|
||||
termcrit.max_iter = MAX(termcrit.max_iter,1);
|
||||
termcrit.max_iter = MIN(termcrit.max_iter,100);
|
||||
termcrit.maxCount = 5;
|
||||
termcrit.maxCount = MAX(termcrit.maxCount,1);
|
||||
termcrit.maxCount = MIN(termcrit.maxCount,100);
|
||||
if( !(termcrit.type & CV_TERMCRIT_EPS) )
|
||||
termcrit.epsilon = 1.f;
|
||||
termcrit.epsilon = MAX(termcrit.epsilon, 0.f);
|
||||
@ -435,7 +423,7 @@ cvPyrMeanShiftFiltering( const CvArr* srcarr, CvArr* dstarr,
|
||||
c0 = sptr[0], c1 = sptr[1], c2 = sptr[2];
|
||||
|
||||
// iterate meanshift procedure
|
||||
for( iter = 0; iter < termcrit.max_iter; iter++ )
|
||||
for( iter = 0; iter < termcrit.maxCount; iter++ )
|
||||
{
|
||||
uchar* ptr;
|
||||
int x, y, count = 0;
|
||||
@ -507,7 +495,7 @@ cvPyrMeanShiftFiltering( const CvArr* srcarr, CvArr* dstarr,
|
||||
s1 = cvRound(s1*icount);
|
||||
s2 = cvRound(s2*icount);
|
||||
|
||||
stop_flag = (x0 == x1 && y0 == y1) || abs(x1-x0) + abs(y1-y0) +
|
||||
stop_flag = (x0 == x1 && y0 == y1) || std::abs(x1-x0) + std::abs(y1-y0) +
|
||||
tab[s0 - c0 + 255] + tab[s1 - c1 + 255] +
|
||||
tab[s2 - c2 + 255] <= termcrit.epsilon;
|
||||
|
||||
@ -526,16 +514,24 @@ cvPyrMeanShiftFiltering( const CvArr* srcarr, CvArr* dstarr,
|
||||
}
|
||||
}
|
||||
|
||||
void cv::pyrMeanShiftFiltering( InputArray _src, OutputArray _dst,
|
||||
double sp, double sr, int maxLevel,
|
||||
TermCriteria termcrit )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_IMPL void cvWatershed( const CvArr* _src, CvArr* _markers )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
|
||||
if( src.empty() )
|
||||
return;
|
||||
|
||||
_dst.create( src.size(), src.type() );
|
||||
CvMat c_src = src, c_dst = _dst.getMat();
|
||||
cvPyrMeanShiftFiltering( &c_src, &c_dst, sp, sr, maxLevel, termcrit );
|
||||
cv::Mat src = cv::cvarrToMat(_src), markers = cv::cvarrToMat(_markers);
|
||||
cv::watershed(src, markers);
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL void
|
||||
cvPyrMeanShiftFiltering( const CvArr* srcarr, CvArr* dstarr,
|
||||
double sp0, double sr, int max_level,
|
||||
CvTermCriteria termcrit )
|
||||
{
|
||||
cv::Mat src = cv::cvarrToMat(srcarr);
|
||||
const cv::Mat dst = cv::cvarrToMat(dstarr);
|
||||
|
||||
cv::pyrMeanShiftFiltering(src, dst, sp0, sr, max_level, termcrit);
|
||||
}
|
||||
|
||||
|
@ -699,7 +699,6 @@ public:
|
||||
private:
|
||||
Mat src;
|
||||
Mat dst;
|
||||
int nStripes;
|
||||
|
||||
double thresh;
|
||||
double maxval;
|
||||
|
@ -90,30 +90,20 @@ void CV_DisTransTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
if( cvtest::randInt(rng) & 1 )
|
||||
{
|
||||
mask_size = 3;
|
||||
dist_type = cvtest::randInt(rng) % 4;
|
||||
dist_type = dist_type == 0 ? CV_DIST_C : dist_type == 1 ? CV_DIST_L1 :
|
||||
dist_type == 2 ? CV_DIST_L2 : CV_DIST_USER;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask_size = 5;
|
||||
dist_type = cvtest::randInt(rng) % 10;
|
||||
dist_type = dist_type == 0 ? CV_DIST_C : dist_type == 1 ? CV_DIST_L1 :
|
||||
dist_type < 6 ? CV_DIST_L2 : CV_DIST_USER;
|
||||
}
|
||||
|
||||
dist_type = cvtest::randInt(rng) % 3;
|
||||
dist_type = dist_type == 0 ? CV_DIST_C : dist_type == 1 ? CV_DIST_L1 : CV_DIST_L2;
|
||||
|
||||
// for now, check only the "labeled" distance transform mode
|
||||
fill_labels = 0;
|
||||
|
||||
if( !fill_labels )
|
||||
sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(0,0);
|
||||
|
||||
if( dist_type == CV_DIST_USER )
|
||||
{
|
||||
mask[0] = (float)(1.1 - cvtest::randReal(rng)*0.2);
|
||||
mask[1] = (float)(1.9 - cvtest::randReal(rng)*0.8);
|
||||
mask[2] = (float)(3. - cvtest::randReal(rng));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -490,6 +490,7 @@ _exit_:
|
||||
comp[2] = r.y;
|
||||
comp[3] = r.width - r.x + 1;
|
||||
comp[4] = r.height - r.y + 1;
|
||||
#if 0
|
||||
if( mask_only )
|
||||
{
|
||||
double t = area ? 1./area : 0;
|
||||
@ -500,6 +501,11 @@ _exit_:
|
||||
comp[5] = s0;
|
||||
comp[6] = s1;
|
||||
comp[7] = s2;
|
||||
#else
|
||||
comp[5] = new_val.val[0];
|
||||
comp[6] = new_val.val[1];
|
||||
comp[7] = new_val.val[2];
|
||||
#endif
|
||||
comp[8] = 0;
|
||||
}
|
||||
|
||||
|
@ -134,6 +134,9 @@ void CV_HoughLinesTest::run_test(int type)
|
||||
read( fs["exp_lines"], exp_lines, Mat() );
|
||||
fs.release();
|
||||
|
||||
if( exp_lines.size != lines.size )
|
||||
transpose(lines, lines);
|
||||
|
||||
if ( exp_lines.size != lines.size || norm(exp_lines, lines, NORM_INF) > 1e-4 )
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
|
@ -111,6 +111,8 @@ void CV_MomentsTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
types[INPUT][0] = CV_MAKETYPE(depth, cn);
|
||||
types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
|
||||
sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(MOMENT_COUNT,1);
|
||||
if(CV_MAT_DEPTH(types[INPUT][0])>=CV_32S)
|
||||
sizes[INPUT][0].width = MAX(sizes[INPUT][0].width, 3);
|
||||
|
||||
is_binary = cvtest::randInt(rng) % 2 != 0;
|
||||
coi = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user