Merge pull request #3444 from Sync-my-L2P:patch-1

This commit is contained in:
Vadim Pisarevsky 2014-12-26 14:40:28 +00:00
commit 61991a3330

View File

@ -48,7 +48,7 @@
namespace cv
{
// A node represents a pixel to label
struct WSNode
{
int next;
@ -56,6 +56,7 @@ struct WSNode
int img_ofs;
};
// Queue for WSNodes
struct WSQueue
{
WSQueue() { first = last = 0; }
@ -86,18 +87,26 @@ allocWSNodes( std::vector<WSNode>& storage )
void cv::watershed( InputArray _src, InputOutputArray _markers )
{
const int IN_QUEUE = -2;
const int WSHED = -1;
// Labels for pixels
const int IN_QUEUE = -2; // Pixel visited
const int WSHED = -1; // Pixel belongs to watershed
// possible bit values = 2^8
const int NQ = 256;
Mat src = _src.getMat(), dst = _markers.getMat();
Size size = src.size();
// Vector of every created node
std::vector<WSNode> storage;
int free_node = 0, node;
// Priority queue of queues of nodes
// from high priority (0) to low priority (255)
WSQueue q[NQ];
// Non-empty queue with highest priority
int active_queue;
int i, j;
// Color differences
int db, dg, dr;
int subs_tab[513];
@ -106,6 +115,7 @@ void cv::watershed( InputArray _src, InputOutputArray _markers )
// MIN(a,b) = a - MAX(a-b,0)
#define ws_min(a,b) ((a) - subs_tab[(a)-(b)+NQ])
// Create a new node with offsets mofs and iofs in queue idx
#define ws_push(idx,mofs,iofs) \
{ \
if( !free_node ) \
@ -122,6 +132,7 @@ void cv::watershed( InputArray _src, InputOutputArray _markers )
q[idx].last = node; \
}
// Get next node from queue idx
#define ws_pop(idx,mofs,iofs) \
{ \
node = q[idx].first; \
@ -134,6 +145,7 @@ void cv::watershed( InputArray _src, InputOutputArray _markers )
iofs = storage[node].img_ofs; \
}
// Get highest absolute channel difference in diff
#define c_diff(ptr1,ptr2,diff) \
{ \
db = std::abs((ptr1)[0] - (ptr2)[0]);\
@ -147,9 +159,14 @@ void cv::watershed( InputArray _src, InputOutputArray _markers )
CV_Assert( src.type() == CV_8UC3 && dst.type() == CV_32SC1 );
CV_Assert( src.size() == dst.size() );
// Current pixel in input image
const uchar* img = src.ptr();
// Step size to next row in input image
int istep = int(src.step/sizeof(img[0]));
// Current pixel in mask image
int* mask = dst.ptr<int>();
// Step size to next row in mask image
int mstep = int(dst.step / sizeof(mask[0]));
for( i = 0; i < 256; i++ )
@ -166,7 +183,7 @@ void cv::watershed( InputArray _src, InputOutputArray _markers )
for( i = 1; i < size.height-1; i++ )
{
img += istep; mask += mstep;
mask[0] = mask[size.width-1] = WSHED;
mask[0] = mask[size.width-1] = WSHED; // boundary pixels
for( j = 1; j < size.width-1; j++ )
{
@ -174,6 +191,7 @@ void cv::watershed( InputArray _src, InputOutputArray _markers )
if( m[0] < 0 ) m[0] = 0;
if( m[0] == 0 && (m[-1] > 0 || m[1] > 0 || m[-mstep] > 0 || m[mstep] > 0) )
{
// Find smallest difference to adjacent markers
const uchar* ptr = img + j*3;
int idx = 256, t;
if( m[-1] > 0 )
@ -193,6 +211,8 @@ void cv::watershed( InputArray _src, InputOutputArray _markers )
c_diff( ptr, ptr + istep, t );
idx = ws_min( idx, t );
}
// Add to according queue
assert( 0 <= idx && idx <= 255 );
ws_push( idx, i*mstep + j, i*istep + j*3 );
m[0] = IN_QUEUE;
@ -221,6 +241,8 @@ void cv::watershed( InputArray _src, InputOutputArray _markers )
int* m;
const uchar* ptr;
// Get non-empty queue with highest priority
// Exit condition: empty priority queue
if( q[active_queue].first == 0 )
{
for( i = active_queue+1; i < NQ; i++ )
@ -231,35 +253,44 @@ void cv::watershed( InputArray _src, InputOutputArray _markers )
active_queue = i;
}
// Get next node
ws_pop( active_queue, mofs, iofs );
// Calculate pointer to current pixel in input and marker image
m = mask + mofs;
ptr = img + iofs;
t = m[-1];
// Check surrounding pixels for labels
// to determine label for current pixel
t = m[-1]; // Left
if( t > 0 ) lab = t;
t = m[1];
t = m[1]; // Right
if( t > 0 )
{
if( lab == 0 ) lab = t;
else if( t != lab ) lab = WSHED;
}
t = m[-mstep];
t = m[-mstep]; // Top
if( t > 0 )
{
if( lab == 0 ) lab = t;
else if( t != lab ) lab = WSHED;
}
t = m[mstep];
t = m[mstep]; // Bottom
if( t > 0 )
{
if( lab == 0 ) lab = t;
else if( t != lab ) lab = WSHED;
}
// Set label to current pixel in marker image
assert( lab != 0 );
m[0] = lab;
if( lab == WSHED )
continue;
// Add adjacent, unlabeled pixels to corresponding queue
if( m[-1] == 0 )
{
c_diff( ptr, ptr - 3, t );