This article refers to this article, because the code that it posted is inefficient and does not conform to my own ideas and habits, so it has been redesigned algorithm and code rewrite.
The so-called connected domain of the image refers to a point 22 with the same or similar pixel value on the image . adjacent to the an area of the form. For adjacency, there are four adjacency and eight adjacency two, as follows:
Four adjacency eight adjacency
As shown by the ' O ' adjacent to ' X ', this article takes a 4 adjacency method.
when looking for an image connected domain, it is generally necessary to go through a binary process, simplifying the pixel value of the image into an either-or-one condition, and then traversing the image to find that one of the values is composed of several connected domains. as shown in the following:
The image after two value processing, two values: Black->255, White->0, we can use the algorithm to find out where the black is composed of how many connected domains, and each connected domain color. The diagram also serves as an example diagram for this article.
Connected domain search algorithm is the core of this paper, referring to the above article mentioned in the two search algorithm, proposed a can traverse the results of the algorithm, the flow of the algorithm is as follows (the process may feel very confusing, the proposed main look at the code, and to provide a look):
1. Traverse the image, once the pixel value is not 0 pixels into the 2nd step
2. Determine if the pixel belongs to a connected domain and if it does not belong to any known connected domain enter 3rd (a), if it belongs to a known connected domain enter 3rd (b) Step
3 (a). Add the connected domain count by 1 and assign the count value to this pixel as a flag for the connected field, and record the value to a corresponding location in an array of mapping relationships, such as a[3]=3. Go back to the 1th step to continue.
3 (b). Compare the pixel value with the value of the pixel above and below the pixel value that is not 0, find the minimum value assigned to all nonzero pixels as the connected domain flag, and adjust the mapping relationship array. Go back to the 1th step to continue.
4. Through the above traversal, the mapping relationship array records the modified image of the connected domain information, however, the information is messy, the same connected domain may be marked by several values, by traversing the array can adjust the situation, the mapping value of the same connected domain with its minimum value to flag.
5. Traverse the image and map the relationship array to adjust the value of the connected domain, through this step the same connected domain will have the same pixel value
6. Color the same connected domain based on the same pixel values
The implementation code is as follows (to facilitate the use of OPENCV, however, it does not use many of its complex functions, as long as a slight modification can be used to directly process the image of the RGB data area):
#include <time.h> #include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp>//opencv contains header files # Include <opencv2/highgui/highgui.hpp> #include <vector>//container header file using namespace std;using namespace Cv;int valuearray[1000] = {0};//record connected field value correspondence class Colorobj{public:int value; Scalar MyColor;}; Vector<colorobj> setcolor;//collects grayscale objects that need to be shaded bool Equal255or0 (int &value)//Determine if the element equals 255 or 0{if (value = = 255 | | Value = = 0) {return true;} Else{return false;}} void SetValue (int &value, int &minimun)//Set pairing value {if (value! = 0) {if (Valuearray[value] > Minimun) {valuearray[ Value] = minimun;} Value = Minimun;}} void Compare (int &value, int &minimun)//Compare size {if (value! = 0) {if (minimun>=value) {minimun = value;}}} Scalar Getrandomcolor ()//color display {Uchar R = 255 * (rand ()/(1.0 + Rand_max)); Uchar g = 255 * (rand ()/(1.0 + Rand_max); Ucha R B = 255 * (rand ()/(1.0 + Rand_max)); return Cv::scalar (b, G, r);} void Main () {Long time = clock ();//Record calculation time mat Image = Cv::imread ("Untitled. png", 0);//read in the image and grayscale the image threshold (image, image, 255, CV_THRESH_BINARY_INV);//Two Value image//imshow ("a", image); int Contourmark = 1; Connected domain Flag Mat intimage;//Picture object, used to convert the pixel variable of an image from Uchar to int, to prevent Image.convertto (Intimage, CV_32SC1) where the subsequent flag bit is larger than the 255 program does not work; Convert image pixel variable to int//traverse image, search for connected domain for (int Y = 1; Y < intimage.rows-1; y++)//traverse the image, Y is the row, and X is the column for (int X = 1; X < intimage.cols-1; X + +) {if (intimage.at<int> (Y, X)! = 0)//Remember here is the antecedent after column {//If it does not belong to any one connected domain if (equal255or0 (intimage.at<int> (Y-1, X)) &&//above element Equal255or0 (intimage.at<int> (y + 1, X)) &&//element below Equal255or0 (intimage.at<int> (y , X-1)) &&//Left element Equal255or0 (intimage.at<int> (Y, X + 1))//Right element {Valuearray[contourmark] = Contourmark;i Ntimage.at<int> (Y, x) = Contourmark;if (Intimage.at<int> (Y-1, x) = = 255) {intimage.at<int> (Y-1, x) = Contourmark;} if (intimage.at<int> (y + 1, x) = = 255) {intimage.at<int> (y + 1, x) = Contourmark;} if (intimage.at<int> (Y, X-1) = = 255) {intimage.at<Int> (Y, X-1) = Contourmark;} if (intimage.at<int> (y, x + 1) = = 255) {intimage.at<int> (y, x + 1) = Contourmark;} contourmark++;} else//already belongs to a connected domain {int getminimum = intimage.at<int> (Y, x);//Get up and down the smallest flag bit compare (intimage.at<int> (Y-1, X) , getminimum); compare (intimage.at<int> (y + 1, X), getminimum); compare (Intimage.at<int> (y, X-1), Getminimum) Compare (Intimage.at<int> (y, X + 1), getminimum),//assigns the smallest flag bit to the target SetValue (intimage.at<int> (Y, x), Getminimum), SetValue (intimage.at<int> (Y-1, x), Getminimum), SetValue (intimage.at<int> (Y + 1, x), Getminimum) SetValue (intimage.at<int> (y, X-1), Getminimum) SetValue (intimage.at<int> (y, X + 1), getminimum);}}} for (size_t i = 1; i < Contourmark; i++)//The Object mapping table of the same connected domain is adjusted well, done this step to complete the mapping table production {//printf ("%d%d\n", I, Valuearray[i]); Valuearr Ay[i] = Valuearray[valuearray[i]];} for (int Y = 1; Y < intimage.rows; y++)//The image pixel is re-assigned according to the mapping table for (int X = 1; X < Intimage.cols; X + +) {if (intimage.at<Int> (y, x)! = 0) {intimage.at<int> (y, x) = Valuearray[intimage.at<int> (y, x)];}} for (int j = 1; j < Contourmark; J + +)//Gets the object value to be shaded {if (valuearray[j]! = j) {bool Dopush = true;for (int i = 0; i < set Color.size (); i++) {if (Setcolor[i].value = = Valuearray[j]) {dopush = False;break;}} if (Dopush = = True) {Colorobj Mycolorobj;mycolorobj.value = Valuearray[j];mycolorobj.mycolor = Getrandomcolor (); Setcolor.push_back (Mycolorobj);}}} Color display Mat colorlabelimg;colorlabelimg.create (intimage.rows, Intimage.cols, cv_8uc3); colorlabelimg = Scalar::all (255 );//Initialize, set the background of the picture to be displayed to white for (int Y = 0; Y < intimage.rows; y++) for (int X = 0; X < Intimage.cols; X + +) {if (intimage.at<int> (y, x)! = 0) {for (int i = 0; i < setcolor.size (); i++) {if (intimage.at<int> (y, x) = = Setcolor[i].value) {colorlabelimg.at<vec3b> (Y, X) [0] = setcolor[i].mycolor[0];colorlabelimg.at<vec3b > (y, x) [1] = setcolor[i].mycolor[1];colorlabelimg.at<vec3b> (y, x) [2] = setcolor[i].mycolor[2];Break;}}}} printf ("Flag bit value%d\n", Contourmark);p rintf ("Spend time%dms\n", clock ()-hour), Imshow ("colorlabelimg", colorlabelimg); Waitkey (0);}
the results of the processing are as follows:
OK, done, reprint remember to indicate the source: the original address
C + + image processing (6) research on search and separate coloring algorithm of------image's connected domain