Search code examples
c#image-processingemgucv

Detect Door Shape in Floor plan using C#


I am working on raster images drawing , so my target is to detect only Door Shapes I am using Emgu C# and applied Haris Corner algorithm , with threshold = 50 and then detect a matrix of corners then calculate the distance between two points to proximate that the two points are start & end of door shape The Problem:
I can't filter image for best detection like how to remove all texts and noise only keep bold walls [![enter image description here][1]][1] [![enter image description here][2]][2]

var img = imgList["Input"].Clone();            
                var gray = img.Convert<Gray, byte>().ThresholdBinaryInv(new Gray(100), new Gray(100)); ;
                imageBoxEx2.Image = gray.ToBitmap();
                var corners = new Mat();
                CvInvoke.CornerHarris(gray, corners,2);
                CvInvoke.Normalize(corners, corners, 255, 0, Emgu.CV.CvEnum.NormType.MinMax);
                Matrix<float> matrix = new Matrix<float>(corners.Rows, corners.Cols);
                corners.CopyTo(matrix);
                dt.Rows.Clear();
                List<Point> LstXpoints = new List<Point>();
                List<Point> LstYpoints = new List<Point>();
                List<PointF> LstF = new List<PointF>();
                for (int i = 0; i < matrix.Rows; i++)
                {
                    for (int j = 0; j < matrix.Cols; j++)
                    {
                        if (matrix[i, j] > threshold)
                        {

                            LstXpoints.Add(new Point ( j, i));
                            LstYpoints.Add(new Point(i, j));
                           // CvInvoke.Circle(img, new Point(j, i), 5, new MCvScalar(0, 0, 255), 3);
                        }
                    }
                }

Solution

  • Sorry for the python code. But perhaps this will help solve your problem. See comments.

    import cv2 
    
    img = cv2.imread('NHoXn.jpg')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # convert to binary image
    thresh=cv2.threshold(gray, 220, 255, cv2.THRESH_BINARY )[1]
    
    #  Morphological reconstruction (delete labels)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
    kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
    marker = cv2.dilate(thresh,kernel,iterations = 1)
    while True:
        tmp=marker.copy()
        marker=cv2.erode(marker, kernel2)
        marker=cv2.max(thresh, marker)
        difference = cv2.subtract(tmp, marker)
        if cv2.countNonZero(difference) == 0:
            break
    
    
    # only walls
    se=cv2.getStructuringElement(cv2.MORPH_RECT, (4,4))
    walls=cv2.morphologyEx(marker, cv2.MORPH_CLOSE, se)
    walls=cv2.erode(walls, kernel2,iterations=2)
    
    # other objects
    other=cv2.compare(marker,walls, cv2.CMP_GE)
    other=cv2.bitwise_not(other)
    
    # find connected components and select by size and area
    output = cv2.connectedComponentsWithStats(other, 4, cv2.CV_32S)
    num_labels = output[0]
    labels = output[1]
    stats=output[2]
    centroids = output[3]
    for i in range(num_labels):
        left,top,width,height,area=stats[i]
        if abs(width-40)<12 and abs(height-40)<12 and area>85:
             cv2.rectangle(img,(left, top), (left+width, top+height), (0,255,0))
    
    cv2.imwrite('doors.png', img)
    

    Result: enter image description here

    1. What is shown in the drawing: walls, doors, windows, furniture, text labels.
    2. The doors to be found always touch the walls.
    3. How are walls different from other objects? Thick, these lines are bold. Thus, dilatation with the desired structural element can leave only parts of the walls. And then, by morphological reconstruction, restore the walls together with the elements that concern them: doors, windows in the first place. The drawing will be cleaned of everything that does not touch the walls.
    4. If dilatation and then erosion are further done, then only walls will remain, thin elements, like windows and doors will disappear.
    5. Subtracting (or logical operations) from the third stage the fourth we get a picture that contains only doors, windows and furniture that touched the walls.
    6. What is the difference in the drawing of the door from the windows? The fact that their BB is almost square, the size is approximately the same for all doors in this drawing, their length is approximately equal to r*(1+pi/4). Further in the code there is a selection for such signs. At this stage, you can add some more signs that will more accurately separate the doors from other elements.