draw a border around detected object in c#

it is the continuation after a previous post.

in my past post i detected object based on color. and got below result. like in images below

but i want only one region around my detected object. for draw that i take all the points of rectangle start position and ending position. start position is upper-left corner and endng poistion is lower-right corner of the rectangle. Then using this position i draw a convex hull. so steps are 2

  • collect all points
  • Draw convex hull

so for collecting all the points i add next few line of code

 List pos = new List();
Rectangle[] rects = blobCounter.GetObjectRectangles();
  if (rects.Length > 3)
            {
                foreach (Rectangle objectRect in rects)
                {
                    Point p = objectRect.Location;
                    pos.Add(p); //add start position
                    p.X= objectRect.X + objectRect.Width;
                    p.Y = objectRect.Y + objectRect.Height;
                    pos.Add(p); //add ending position
                }

objectRect.Location return starting location and by sum the height and width we get ending location

Now draw the convexhull, from net a very nice function to draw convex hull, u can see that here . so for draw convexhull i had to write bellow code

  Graphics g = Graphics.FromImage(image3);
                 List hull = null;

                // Get the convex hull.
           hull = MakeConvexHull(pos);//pos is collection of rectangles position

                using (Pen pen = new Pen(Color.FromArgb(160, 255, 160), 5))
                {
                    Point[] hull_points = new Point[ hull.Count];
                    hull.CopyTo(hull_points);
                    g.DrawPolygon(pen, hull_points);
                }
                g.Dispose();

and we get below image
the function make convex hull u can find here in geometryclass. from  that class i only add below code in my class

  public static Point[] g_MinMaxCorners;
        public static Rectangle g_MinMaxBox;
        public static Point[] g_NonCulledPoints;
  public static List MakeConvexHull(List points)
        {
            // Cull.
            points = HullCull(points);

            // Find the remaining point with the smallest Y value.
            // if (there's a tie, take the one with the smaller X value.
            Point best_pt = points[0];
            foreach (Point pt in points)
            {
                if ((pt.Y < best_pt.Y) ||
                   ((pt.Y == best_pt.Y) && (pt.X < best_pt.X)))
                {
                    best_pt = pt;
                }
            }

            // Move this point to the convex hull.
            List hull = new List();
            hull.Add(best_pt);
            points.Remove(best_pt);

            // Start wrapping up the other points.
            float sweep_angle = 0;
            for (; ; )
            {
                // Find the point with smallest AngleValue
                // from the last point.
                int X = hull[hull.Count - 1].X;
                int Y = hull[hull.Count - 1].Y;
                best_pt = points[0];
                float best_angle = 3600;

                // Search the rest of the points.
                foreach (Point pt in points)
                {
                    float test_angle = AngleValue(X, Y, pt.X, pt.Y);
                    if ((test_angle >= sweep_angle) &&
                        (best_angle > test_angle))
                    {
                        best_angle = test_angle;
                        best_pt = pt;
                    }
                }

                // See if the first point is better.
                // If so, we are done.
                float first_angle = AngleValue(X, Y, hull[0].X, hull[0].Y);
                if ((first_angle >= sweep_angle) &&
                    (best_angle >= first_angle))
                {
                    // The first point is better. We're done.
                    break;
                }

                // Add the best point to the convex hull.
                hull.Add(best_pt);
                points.Remove(best_pt);

                sweep_angle = best_angle;

                // If all of the points are on the hull, we're done.
                if (points.Count == 0) break;
            }

            return hull;
        }
        private static float AngleValue(int x1, int y1, int x2, int y2)
        {
            float dx, dy, ax, ay, t;

            dx = x2 - x1;
            ax = Math.Abs(dx);
            dy = y2 - y1;
            ay = Math.Abs(dy);
            if (ax + ay == 0)
            {
                // if (the two points are the same, return 360.
                t = 360f / 9f;
            }
            else
            {
                t = dy / (ax + ay);
            }
            if (dx < 0)
            {
                t = 2 - t;
            }
            else if (dy < 0)
            {
                t = 4 + t;
            }
            return t * 90;
        }

    }

hope that much is useful.

for download code click here

About kishor datta gupta

Graduate Research Assistant at University of Memphis Software Engineer at Silicon Orchard LTD. Former Research Assistant at Lamar University Former Software Engineer at Samsung R&D Institute Bangladesh Studies Ph.D. Computer Science at University of Memphis Studied Masters of Science in Computer Sciences at Lamar University Studied BSC in CSE at Khulna University of Engineering and Technology Studied HSC (completed) at Chittagang college 04-06 Studied High school at ST. Placid's High School'04 Studied Junior Secondary School at Saint Mary's School Lives in Memphis, Tennessee
This entry was posted in C#, Image Processing, Winform app and tagged , , , , , , , , . Bookmark the permalink.

26 Responses to draw a border around detected object in c#

  1. thanks for this articel, but where link to download this code,,,,??? this is very usefull for me

  2. javier says:

    your samples ares amazing! i´m very glad to have found your web site. where can i check this code?
    thank u a lot

  3. jasmine89 says:

    hi , it’s me again can we communicate if you can ?
    I’m a little bit confused about how the storing is going to be …
    I made a color detection with a colored gloves – it’s a black and i want to use two colors with it red and yellow – i don’t want to use many colors –
    I want to make the numbers , letters , and certain number of the static words
    but still there’s two problems :
    1- what is the best way to put the colors on the glove so i can get all the signs by the camera
    2- then how I’m going to store that sign

    • kishordgupta says:

      if u want to use more than one color , it would be best to use different thread to use different color , after the detection u need to extract the part of the image where object located and than store the extracted part as a image file.
      and then u can use neural network on that image file like the below link

      http://www.codeproject.com/KB/recipes/NNHandwrittenCharRecCs.aspx

      feel free to ask me any question. i will be happy to help

      • jasmine89 says:

        thanks a lot for you
        1- do you mean i have to detect the yellow color in a vedioSource and the red color in other separate one ?
        2- I want to ask you about the YCrCb system color ,
        I found that there are four filters so I used the same procedure you used in your processing but with those filters
        but it didn’t do any thing 😦
        so here’s my question : in the first part of your code
        you apply a certain filter with a specific color on the image then you use the blob filter to get that detected color then draw rectangles around the detected region
        Is that TRUE .i.e. do i understand it well ?
        and if it’s right why mine is not working !!
        take a look on my procedure :

        void process3_YCbCrFiltering(YCbCr color, YCbCrFiltering filter, ref Bitmap image)
        {
        // create filter
        filter = new YCbCrFiltering();
        // set color ranges to keep
        //filter.Cb = new DoubleRange(-0.2, 0);
        //filter.Cr = new DoubleRange(0.26, 0.5);
        filter.FillColor = color;
        // apply the filter

        Bitmap objectsImage = null;
        Bitmap mImage = null;
        mImage = (Bitmap)image.Clone();

        objectsImage = image;
        filter.ApplyInPlace(objectsImage);

        BitmapData objectsData = objectsImage.LockBits(new Rectangle(0, 0, image.Width, image.Height),
        ImageLockMode.ReadOnly, image.PixelFormat);
        UnmanagedImage grayImage = grayscaleFilter.Apply(new UnmanagedImage(objectsData));
        objectsImage.UnlockBits(objectsData);

        blobCounter.ProcessImage(grayImage);
        Rectangle[] rects = blobCounter.GetObjectsRectangles();

        if (rects.Length > 0)
        {

        foreach (Rectangle objectRect in rects)
        {
        Graphics g = Graphics.FromImage(mImage);
        using (Pen pen = new Pen(Color.FromArgb(160, 255, 160), 5))
        {
        g.DrawRectangle(pen, objectRect);
        }

        g.Dispose();
        }
        }

        image = mImage;
        }

        void process1_YCbCrLinear(YCbCr color, YCbCrLinear filter, ref Bitmap image)
        {
        filter = new YCbCrLinear();
        // configure the filter
        filter.InCb = new DoubleRange(-0.5, 0.5);
        filter.InCr = new DoubleRange(-0.5, 0.5);
        filter.InY = new DoubleRange(0, 1);
        // apply the filter

        Bitmap objectsImage = null;
        Bitmap mImage = null;
        mImage = (Bitmap)image.Clone();

        objectsImage = image;
        filter.ApplyInPlace(objectsImage);

        BitmapData objectsData = objectsImage.LockBits(new Rectangle(0, 0, image.Width, image.Height),
        ImageLockMode.ReadOnly, image.PixelFormat);
        UnmanagedImage grayImage = grayscaleFilter.Apply(new UnmanagedImage(objectsData));
        objectsImage.UnlockBits(objectsData);

        blobCounter.ProcessImage(grayImage);
        Rectangle[] rects = blobCounter.GetObjectsRectangles();

        if (rects.Length > 0)
        {

        foreach (Rectangle objectRect in rects)
        {
        Graphics g = Graphics.FromImage(mImage);
        using (Pen pen = new Pen(Color.FromArgb(160, 255, 160), 5))
        {
        g.DrawRectangle(pen, objectRect);
        }

        g.Dispose();
        }
        }

        image = mImage;
        }

        • kishordgupta says:

          1-yes
          2- you understand the process correctly but i use euclidean filtering not YCbCr filter.
          different between those two method is huge, in euclidean only get the object in ur given color. but in yCbCR ur given color is remove from the picture.
          use euclidean filtering.

          thnx

          • jasmine89 says:

            thannnnks very much
            actually the lightining was making a problem so our headmaster suggest us to change the color system from RGB to another one just like
            YCrCb , HSL , Normalized RGB
            and he recommended YCrCb so i did that ,
            I didn’t knew what its work ,thoght it’s just like
            euclidean .
            I’m confused now ! how can I use euclidean filter with YCrCb color ??

          • jasmine89 says:

            thannnnks very much
            actually the lightning was making a problem so our headmaster suggest us to change the color system from RGB to another one just like
            YCrCb , HSL , Normalized RGB
            and he recommended YCrCb so i did that ,
            I didn’t knew what its work ,thoght it’s just like
            euclidean .
            I’m confused now ! how can I use euclidean filter with YCrCb color ??

  4. jasmine89 says:

    hey , it’s me again
    I’ve solved the lightning problem by using the YCbCr color space
    and now I can get the whole colors i need in the picture
    but I Still don’t know how can I get the position of the colors
    I mean
    I need to know where does the red color for the yellow one (right , above … etc)
    and the distance between the colors in the grayscale filtering so I know how do fingers stand

  5. husna says:

    hi, can u send me the link to download the code? i’m going to test on my eye image to check whether it is effective to use or not..big thank you for the code..

  6. Paco says:

    Excelent article and many thanks!
    The download link seems to be broken. Have you an alternative way for gettting it?
    Thank you!

  7. PhongTran says:

    Can you send me soure code of Project Detect object from image based on object color.Thank you very much,your work is amazing!!!

  8. Alexander says:

    Can you send me a code? LInk doesn’t work
    sopholos@sopholos.ru

  9. Le Minh Tam says:

    Please Send Your Source Code to my emal leminhtamboy@gmail.com
    Thanh you very much

Leave a comment