A 2-channel algorithm code__ algorithm for image connected domain detection

Source: Internet
Author: User
Tags new set set set

This algorithm describes the reference link: http://blog.csdn.net/icvpr/article/details/10259577

two times scanning method:


(1) First scan:

Access current pixel B (x,y) if B (x,y) = = 1:

A, if the pixel value in the field of B (X,y) is 0, give B (x,y) a new label:

Label + = 1, B (x,y) = label;

b, if the domain of B (x,y) has pixel value > 1 pixel neighbors:

1 assigns the minimum value in the neighbors to B (x,y):

B (x,y) = min{neighbors}

(2) record the equivalence between the values (labels) in the neighbors, that is, the values (label) belong to the same connected region;

Labelset[i] = {label_m, ..., Label_n},labelset[i] All of the labels belong to the same connected region (note: There can be many ways to do this, as long as you can record the relationships between the labels that have an equality relationship)

(2) Second scan:

Access current pixel B (x,y) if B (x,y) > 1:

A, finding a minimum label value that is equivalent to the label = B (X,y), given to B (X,y);
After the scan is complete, pixels with the same label value in the image form the same connected region.



Algorithm Code:

Intuitively, the two-way method is faster than the Stack method, in fact the speed is only 1/5-1/10 of the stack method, the code is as follows:

Using the two-pass scan//Find all connected domains//simple methods, use the 1-0 matrix//column marking method to collect all connected domains//need to use the inverted index bool Cd2detectinpic::searchconby2way (const CV::MAT 
	& _binimg, float Valueforeb, float valueforeup, STD::VECTOR<STD::VECTOR<CV::P oint > > &foreareas) {
	int vfore = 255;
	int vback = 0;
	Foreareas.resize (0);
	Cv::mat _lableimg;
	if (_binimg.channels () >1) {Cv::cvtcolor (_binimg,_lableimg,cv::color_bgr2gray);
	else {_binimg.copyto (_lableimg);
//scan, get foreground and background points, mark//background Mark 0, foreground point marked as 1 #ifdef show_temp cv::imshow ("", _lableimg);//cv::waitkey (0);
	#endif iplimage Imagelabel = _lableimg;
		for (int i=0;i< imagelabel.height;++i) {char* PI = (char*) imagelabel.imagedata + i * IMAGELABEL.WIDTHSTEP;
			for (int j=0;j<imagelabel.width;++j) {if (*pi >=valueforeb &&*pi <=valueforeup)//Avoid single value errors.
			{*pi = Vfore;
			else {*pi = Vback;
		} ++pi;
	}//The label image is traversed, looking for the connected domain//to mark Matrix, making modifications without modifying the identification matrix Cv::mat ImageMark (&imagelabel); Cv::mat imaGemarkre = Imagemark.clone ();
Use line scanning to separate merge//use Set set to represent equality #ifdef show_temp cv::imshow ("Imagemarkre", imagemarkre);//Cv::waitkey (1);  

	#endif std::stack<std::p air<int,int> > Neighborpixels;
	Use another label matrix to record which connected domain the current point belongs to Cv::mat Conarealocmat = Cv::mat::zeros (_BINIMG.ROWS,_BINIMG.COLS,CV_8UC1);
	Cv::bitwise_not (Conarealocmat,conarealocmat);

	Iplimage imageconarealoc = Conarealocmat;
	STD::VECTOR&LT;STD::p AIR&LT;CV::P oint,uchar> > Conareas (imagemark.cols);

	STD::VECTOR&LT;STD::VECTOR&LT;CV::P oint> > Conpointsareas (0);  Nth connected domain int counter =0;//is used to mark the nth connected domain int idx =0;//for hash index//Set repeating set///For last merge connected domain//std::vector<std::vector<int>
	> Overlapvec (0);

	Std::set<int,int> Overlapset; Std::multimap<int,int> overlapmap;//uses multivalued hashes//to divide the first row into connected domains {char* Plabel = (char*) Imagelabel.imagedata + 0* im
		Agelabel.widthstep;
		char* Ploc = (char*) Imageconarealoc.imagedata + 0* imageconarealoc.widthstep;
int lastl = *plabel;
		if (Vfore = = Lastl) {++counter;

			*ploc = counter;//count starting from 1, the index starts from 0//++idx;
			std::p air<int,int> P (COUNTER,IDX);
		Overlapmap.insert (P);//Insert Index} else {*ploc =-1;
		int lastloc = *ploc;
		++plabel;

		++ploc; for (int n=1; n< imagemark.cols ++n) {if (Vfore = = *plabel)/If marked as connected domain, mark {if (*PLABEL==LASTL)/if and previous
				Pixel Unicom, then marked as the previous tag {*ploc = Lastloc;
					else {//If the previous is 0, add the tag symbol to ++counter the new tag;
					*ploc = counter;

					++idx;
					std::p air<int,int> P (COUNTER,IDX);
				Overlapmap.insert (P);//Insert index//std::cout<< idx << "_" <<counter<<std::endl;
			} else {*ploc = -1;//if it encounters the nth point as the change point, the position labeled nth connected domain} LASTL = *plabel;
			Lastloc = *ploc;
			++ploc;
		++plabel; To find connected fields for each row of the picture, you must traverse for (int m =1; m<imagemark.rows; ++m) {//assign to first pixel///previous line pointer char* Plabelfore =
		(char*) Imagelabel.imagedata + (m-1) * IMAGELABEL.WIDTHSTEP; char* plocforE = (char*) Imageconarealoc.imagedata + (m-1) * IMAGECONAREALOC.WIDTHSTEP;
		The pointer to this line char* Plabel = (char*) Imagelabel.imagedata + m* imagelabel.widthstep;

		char* Ploc = (char*) Imageconarealoc.imagedata + m* imageconarealoc.widthstep;
		Mark the first point, the line above is quasi int forel = *plabelfore;

		int foreloc = *plocfore;

		int lastl = *plabel;
		if (*plabel = = Forel)/If equal to the value on the previous line, the connected field position is equal to the first value of the previous row {*ploc = *plocfore;
				else {if (Vfore = = *plabel) {//If it is a connected domain, increase the markup symbol for the new tag ++counter;
				*ploc = counter;

				++idx;
				std::p air<int,int> P (COUNTER,IDX);
			Overlapmap.insert (P);//Insert index//std::cout<< idx << "_" <<counter<<std::endl;
			else {*ploc =-1;

		an int lastloc = *ploc; for (int n=0; n< imagemark.cols-1 ++n) {//Find the connected domain for each row Lastl = *plabel;//The last pixel's tag lastloc = *ploc;//The last pixel's connection
			Pass-field position//to next pixel ++plabel;
			++ploc;
			++plabelfore;

			++plocfore; Forel = *plabelfore;//on line ThisPosition pixel Value Foreloc = *plocfore;//The connected domain position of the last pixel if (vback = = *plabel)/If the current label is 0 {*ploc =-1; else {if (*plabel!= Forel)//If the current label is not equal to the previous row of pixels, the label {if (*plabel!= lastl) {//If the current label is not equal to the previous
						The label of the Pixel is expressed as the beginning of the new connected domain, and the new set//If the connected domain, then the markup symbol is added to the ++counter;
						*ploc = counter;

						++idx;
						std::p air<int,int> P (COUNTER,IDX);
					Overlapmap.insert (P);//Insert index//std::cout<< idx << "_" <<counter<<std::endl;
					else {//If the current label equals the label of the previous pixel, it is connected, the direct assignment *ploc = Lastloc;
					} else {//if equal to the previous line of pixels, it is troublesome.
					if (*plabel!= lastl)//if not equal to the previous pixel label, the tag {*ploc = Foreloc is assigned to the previous line;
						else {if (Foreloc = = Lastloc)//If the previous and previous row equals {*ploc = Foreloc;

							else {//If the previous and previous line is not equal///if equal to the previous pixel, you need to merge the set//tag the same set *ploc = Foreloc;
					Merge hash table//lookup to the hash index where the value is located int idxf = (*overlapmap.find (foreloc)).		int IDXFL = (*overlapmap.find (lastloc)). First;//map is looking for key instead of value int L1 = (*overlapmap.find (foreloc)). Second;
							
							int L2 = (*overlapmap.find (lastloc)). Second;
								if (L1!= L2)//If not in an index, you can delete {//Insert the current value into the index without increasing the IDX index//must first be deleted and then inserted in order to avoid accidentally deleting//removing the old key value pairs
								Overlapmap.erase (IDXFL);//One parameter is key, is the wrong//int x = Overlapmap.erase (Lastloc);

								Overlapmap.erase (IDXFL);
								std::p air<int,int> P (idxf,lastloc);
								std::p air<int,int> P (LASTLOC,L1);

							Overlapmap.insert (P); 
	} else {}}}}} SYSTEMTIME sys; 
	Getlocaltime (&sys);

	int milets = Sys.wsecond;int Milet = sys.wmilliseconds;
	Direct lookup to position conpointsareas.resize (Overlapmap.size ());
	Iplimage imageconarea= Imageconarealoc;
		for (int i=0;i< imageconarea.height;++i) {char* PI = (char*) imageconarea.imagedata + i * IMAGECONAREA.WIDTHSTEP; for (int j=0;j<imagECONAREA.WIDTH;++J) {if (*pi >0) {cv::P oint P (j,i);
				int idx = (*overlapmap.find ((int) *pi)). Second-1;
			Conpointsareas[idx].push_back (P);
		} ++pi;
	an int validvec = 0;
	Foreareas.resize (Validvec);
			for (int i=0;i< conpointsareas.size (); ++i) {if (Conpointsareas[i].size () >0) {++validvec;
		Foreareas.push_back (Conpointsareas[i]); 
	} getlocaltime (&sys);
	int MileT2 = Sys.wmilliseconds;
	int detat = Milet2-milet;
	std::cout<< Std::endl;
	std::cout<< "The Copyvec Time is:" << detat<< "MS ..." << Std::endl;

	std::cout<< Std::endl;
	Conpointsareas.resize (0);
return true; }

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.