Commit 61991a33 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

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

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