A simple implementation of the diffuse water filling algorithm (QT version)

Source: Internet
Author: User

The so-called diffuse water filling algorithm is a point within a unicom domain, which is the starting point to find all the remaining points of the Unicom domain and populate it as an algorithm for the specified color.
It is called diffuse filling, because this algorithm simulates the swollen process, starting one o'clock, the water gradually increases, until it is diffuse across the entire area.
A detailed description of this algorithm can be found in the links below.
Https://en.wikipedia.org/wiki/Flood_fill

This algorithm is useful when we are looking for a specified area. So it took me a little time to write a program. The algorithm I implemented is similar to the one in the following picture, but I am populating one line at a time.

The following Floodfill_gray function is used to fill the grayscale image, and the gray fill of a unicom domain is newval.

Static inline BOOLFillpoint_gray (Qimage &image, Qpoint p, Uchar Val, Uchar newval, Qstack<qpoint> &Stack){intx = P.rx ();inty = P.ry (); Uchar *line = Image.scanline (y);if(line[x]! = val) {return false; } line[x] = newval;if(Y >0) {Uchar *last = image.scanline (Y-1);if(Last[x] = = val) {Stack. push (Qpoint (x, Y-1)); }    }if(Y < Image.height ()-1) {Uchar *next = image.scanline (y +1);if(Next[x] = = val) {Stack. push (Qpoint (x, y +1)); }    }return true;}BOOLFloodfill_gray (Qimage &image, Qpoint seedpoint, Uchar newval) {if(Image.format ()! = Qimage::format_indexed8) {return false; }intwidth = Image.width ();intHeight = image.height ();intx = Seedpoint.rx ();inty = Seedpoint.ry ();if(X <0|| X >= Width | | Y <0|| Y >= height) {return false; }intValue = Image.scanline (y) [x]; Qstack<qpoint>Stack;Stack. push (Seedpoint); while(!Stack. IsEmpty ()) {Qpoint p =Stack. Pop ();BOOLret = Fillpoint_gray (image, p, value, NewVal,Stack);BOOLRet2 = ret;        y = P.ry ();        x = P.rx (); x--; while(x >=0&& ret) {ret = Fillpoint_gray (image, Qpoint (x, y), value, NewVal,Stack);        x--;        } x = P.rx (); x + +; while(x < width && Ret2) {Ret2 = Fillpoint_gray (Image, Qpoint (x, y), value, NewVal,Stack);        x + +; }    }return true;}

Sometimes, due to noise and other effects, the original color in our area to be filled is not exactly the same, then a fuzzy fill can be used. The so-called fuzzy fill is that we set a range of colors, which are considered to be the inner points of the area within this color range.
The following code implements this function.

Static inline BOOLFillpoint_gray (Qimage &image, Qpoint p, Uchar Low, Uchar High, Uchar newval, Qstack<qpoint> &Stack){intx = P.rx ();inty = P.ry (); Uchar *line = Image.scanline (y);if(Line[x] < low | | line[x] > High) {return false; } line[x] = newval;if(Y >0) {Uchar *last = image.scanline (Y-1);if(Last[x] >= low && last[x] <= High) {Stack. push (Qpoint (x, Y-1)); }    }if(Y < Image.height ()-1) {Uchar *next = image.scanline (y +1);if(Next[x] >= low && next[x] <= High) {Stack. push (Qpoint (x, y +1)); }    }return true;}BOOLFloodfill_gray (Qimage &image, Qpoint Seedpoint,intLowintHigh, Uchar newval) {if(Image.format ()! = Qimage::format_indexed8) {return false; } low = Qbound (0, Low,255); High = Qbound (0, High,255);if(Low > High) {return false; } qstack<qpoint>Stack;Stack. push (Seedpoint);intwidth = Image.width (); while(!Stack. IsEmpty ()) {Qpoint p =Stack. Pop ();BOOLret = Fillpoint_gray (image, p, low, High, newval,Stack);BOOLRet2 = ret;inty = P.ry ();intx = P.rx (); x--; while(x >=0&& ret) {ret = Fillpoint_gray (image, Qpoint (x, y), low, high, newval,Stack);        x--;        } x = P.rx (); x + +; while(x < width && Ret2) {Ret2 = Fillpoint_gray (Image, Qpoint (x, y), low, high, newval,Stack);        x + +; }    }return true;}

I also wrote a color image to fill in. This code is also relatively simple, for the moment has not realized the fuzzy color discrimination. The reason is not written, mainly in the RGB color space, it is not easy to measure the distance between two color values. If you simply use Euclidean distance, it will be somewhat out of touch with our eyes ' perception of color. Maybe we think the color difference is very large two color distance is not far, and the appearance of the two colors may be very large distance.

Static inline BOOLFillpoint_rgb32 (Qimage &image, Qpoint p, Qrgb Val, Qrgb newval, Qstack<qpoint> &Stack){intx = P.rx ();inty = P.ry (); Qrgb *line = (qrgb*) image.scanline (y);if(line[x]! = val) {return false; } line[x] = newval;if(Y >0) {Qrgb *last = (qrgb*) image.scanline (Y-1);if(Last[x] = = val) {Stack. push (Qpoint (x, Y-1)); }    }if(Y < Image.height ()-1) {Qrgb *next = (qrgb*) image.scanline (y +1);if(Next[x] = = val) {Stack. push (Qpoint (x, y +1)); }    }return true;}BOOLFloodfill_rgb32 (Qimage &image, Qpoint seedpoint, Qrgb newval) {qdebug () << Image.format ();if(Image.format ()! = qimage::format_rgba8888 && Image.format ()! = qimage::format_argb32) {return false; }intwidth = Image.width ();intHeight = image.height ();intx = Seedpoint.rx ();inty = Seedpoint.ry ();if(X <0|| X >= Width | | Y <0|| Y >= height) {return false;    } Qrgb value = Image.pixel (x, y); Qstack<qpoint>Stack;Stack. push (Seedpoint); while(!Stack. IsEmpty ()) {Qpoint p =Stack. Pop ();BOOLret = fillpoint_rgb32 (image, p, value, NewVal,Stack);BOOLRet2 = ret;        y = P.ry ();        x = P.rx (); x--; while(x >=0&& ret) {ret = Fillpoint_rgb32 (image, Qpoint (x, y), value, NewVal,Stack);        x--;        } x = P.rx (); x + +; while(x < width && Ret2) {Ret2 = Fillpoint_rgb32 (Image, Qpoint (x, y), value, NewVal,Stack);        x + +; }    }return true;}

Here is a test image.

I'm going to fill the largest red Unicom area with blue. The following is the result of the fill.

However, this algorithm has a note, that is, it only the next and next to the adjacent pixels are considered together, diagonally adjacent pixels are considered to be disconnected. This is designed to handle the following scenario. If the diagonal is also considered to be the same, then all the white areas are connected, which is not the same as our intuitive feeling.

Of course, after this treatment, there are two outliers in the black area that the program considers not to be connected to the other black areas. There is a difference between this and our intuitive feeling. In short, these two situations cannot be taken into account.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

A simple implementation of the diffuse water filling algorithm (QT version)

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.