⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conncomp.cpp

📁 barcode readers [ from Image]
💻 CPP
字号:
//
// ConnComp
//   Finds connected components in a binary (0,255) image.
//   Input is a binary byte image with 0 background and non-zero foreground.
//   Output is a short image with 0 background and each component labeled
//   with a different label.
//
// Copyright (C) 2003, 2006 by Jon A. Webb (Contact via GMail; username is jonawebb)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
//
#include "ConnComp.h"

#include "Image.h"
#include "GrayImageIter.h"
#include "GrayIndex.h"
#include "ImageSize.h"
#include "Replicate.h"
#include "ShortImageIter.h"

#include <e32std.h>
#include <fbs.h>

using namespace Core;

namespace Algorithm
{

	//
	// Lifecycle
	//
	EXPORT_C CConnComp* CConnComp::NewL()
	{	
		CConnComp *me = new (ELeave) CConnComp;
		CleanupStack::PushL(me);
		me->InitializeL();
		CleanupStack::Pop(me);
		return me;	
	}

	CConnComp::~CConnComp()
	{
		User::Free(iTable);
	}

	CConnComp::CConnComp() :
		ibEmpty(true),
		iTable(NULL)
	{
	}

	// Allocate label table and initialize table size.
	void CConnComp::InitializeL()
	{
		ExtendTableL(TableSize);
	}

	// 
	// Operations
	//
	// Return a new label; if the number of labels exceeds the table size
	// double the table size.
	unsigned short CConnComp::NewLabelL() 
	{
		if (++iCurrentLabel >= inCurrentSize) {
			// we can only use up to 2^16 = 65536 labels since the
			// data type used to store them is unsigned short
			const unsigned int twoP16 = 0x10000;
			if (inCurrentSize == twoP16) {
				_LIT(LTooBigErr, "CConnComp: too many labels");
				User::Panic(LTooBigErr, KErrGeneral);
			}
			ExtendTableL(2*inCurrentSize);
		}
		return iCurrentLabel;
	}

	// Merge two labels, by assigning the mapping of one label to the other.
	void CConnComp::Merge(unsigned short l, unsigned short r)
	{
		l = Lookup(l);
		r = Lookup(r);
		while (l != r) {
			unsigned short nL = iTable[l];
			iTable[l] = r;
			l = nL;
		}
	}

	// Look up the mapping for a label. Reduce the chain length for this mapping
	// to 1 in order to ensure very good complexity.
	unsigned short CConnComp::Lookup(unsigned short l)
	{
		unsigned short origL = l;
		while (l != iTable[l]) {
			l = iTable[l];
		}
		while (origL != l) {
			unsigned short nL = iTable[origL];
			iTable[origL] = l;
			origL = nL;
		}
		return l;
	}	

	void CConnComp::ExtendTableL(unsigned int nNewMaxSize)
	{
		if (iTable) {
			iTable = (unsigned short*) 
				User::ReAllocL(
					iTable, 
					sizeof(unsigned short) * nNewMaxSize);
		} else {
			iTable = (unsigned short*) 
				User::AllocL(sizeof(unsigned short) *nNewMaxSize);
		}
		// initialize new entries in table to identity
		unsigned int i;
		for (i=inCurrentSize; i<nNewMaxSize; i++) {
			iTable[i] = (unsigned short) i;
		}
		inCurrentSize = nNewMaxSize;
	}
	
	//
	// Overrides
	//
	CImage CConnComp::FrontL()
	{
		if (ibEmpty) {
			User::Leave(KErrGeneral);
			return CImage();
		}
		ibEmpty = true;
		return iImage;
	}

	// Label an image. 
	// Any non-zero value is treated identically.
	//The code is written so that the input image is
	// never indexed using multiplicative indexing; instead the indexing
	// purely uses IGrayImageIter operators.
	void CConnComp::PushL(CImage image)
	{
        // first convert the input 0, 255 gray image to a binary 0, 1 short image
		// that we can use to store the image labels
		IReplicate rRepl(image);
		CImage imageShort;
		rRepl.CastL(imageShort, EColor64K);
		image.LockLC(); // lock bitmaps
		IGrayImageIter itByte(image);
		IShortImageIter it(imageShort);
		for (; !it.End(); it.NextRow(), itByte.NextRow()) {
			for (; !it.REnd(); it++, itByte++) {
				if (itByte() == 0) {
					it() = 0;
				} else {
					it() = 1;
				}
			}
		}
		// create and initialize iterators for the pixels up and to the left, up, 
		// up and to the right, and left of the current pixel
		//
		// when processing a pixel at 'it' these iterators have the following positions:
		//     itUL  itU  itUR
		//     itL   it
		//
		it.Reset();
		IShortImageIter itUL = it, itU = it, itUR = it, itL = it;
		// Move the iterators down the their correct positions.
		itU++;
		itUR++; 
		itUR++;
		itL.NextRow();
		it.NextRow(); 
		it++;
		// scan the image. whenever two adjacent pixels are non-zero, merge the two
		// labels if they have not already been merged.
		// the first column is special
		if (itL() != 0) {
			itL() = NewLabelL();
		}
		// the first row is special since there is no row above this row.
		while (!it.REnd()) {
			if (it() != 0) {
				if (itL() != 0) {
					it() = itL();
				} else {
					it() = NewLabelL();
				}
			}
			it++;
			itL++;
		}
		// process all other rows in the image.
		while (true) { // break from within when it gets to end
			// it
			it.NextRow(); 
			if (it.End()) {
				break;
			} else { 
				it++; 
			};		
			// go to the next row
			// itUL
			itUL.NextRow();
			// itU
			itU.NextRow(); 
			itU++;
			// itUR
			itUR.NextRow(); 
			itUR++; 
			itUR++;
			// itL
			itL.NextRow();

			// first column is still special
			if (itL() != 0) {
				if (itUL() != 0) {
					itL() = itUL();
				} else {
					itL() = NewLabelL();
				}
			}
			while (!it.REnd()) {
				if (it() != 0) {
					// The pixels we are considering are
					//    itUL    itU    itUR
					//    itL     it
					bool bAssigned = false;
					if (itUL() != 0) {
						it() = itUL();
						bAssigned = true;
					}
					if (itU() != 0) {
						if (bAssigned) {
							Merge(it(), itU());
						}
						it() = itU();
						bAssigned = true;
					}
					if (!itUR.REnd() && itUR() != 0) {
						if (bAssigned) {
							Merge(it(), itUR());
						}
						it() = itUR();
						bAssigned = true;
					}
					if (itL() != 0) {
						if (bAssigned) {
							Merge(itL(), it());
						}
						it() = itL();
					}
					// if no existing label has been assigned, create a new label
					if (!bAssigned) {
						it() = NewLabelL();
					}
				}
				itUL++;
				itU++;
				if (!itUR.REnd()) {
					itUR++;
				}
				itL++;
				it++;
			}

		}

		for (it.Reset(); !it.End(); it.NextRow()) {
			for (; !it.REnd(); it++) {
				if (it() != 0) {
					it() = Lookup(it());
				}
			}
		}
		CleanupStack::PopAndDestroy(); // release bitmaps
		iImage = imageShort;
		ibEmpty = false;
	}

	bool CConnComp::Empty() const
	{
		return ibEmpty;
	}


};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -