mirror of
https://github.com/opencv/opencv.git
synced 2024-11-27 20:50:25 +08:00
Merge pull request #3444 from Sync-my-L2P:patch-1
This commit is contained in:
commit
61991a3330
@ -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 );
|
||||
|
Loading…
Reference in New Issue
Block a user