How to identify different objects in an image?

后端 未结 3 885
孤城傲影
孤城傲影 2021-02-05 12:13

I\'m intending to write a program to detect and differentiate certain objects from a nearly solid background. The foreground and the background have a high contrast difference w

相关标签:
3条回答
  • 2021-02-05 12:28

    If you intend to detect shapes other than just circles, (and from the image I assume you do), I would recommend the Chamfer matching for a quick start, especially as you have a good contrast.

    The basic premise, explained in simple terms, is following:

    1. You do an edge detection (for example, cvCanny in opencv)
    2. You create a distance image, where the value of each pixel means the distance fom the nearest edge.
    3. You take the shapes you would like to detect, define sample points along the edges of the shape, and try to match these points on the distance image. Basically you just add the values on the distance image which are "under" the coordinates of your sample points, given a specific position of your objects.
    4. Find a good minimization algorithm, the effectiveness of this depends on your application.

    This basic approach is a general solution, usually works well, but without further advancements, it is very slow.

    Usually it's a good idea to first separate the objects of interest, so you don't have to always do the full search on the whole image. Find a good threshold, so you can separate objects. You still don't know which object it is, but you only have to do the matching itself in close proximity of this object.

    Another good idea is, instead of doing the full search on the high resolution image, first do it on a very low resolution. The result will not be very accurate, but you can know the general areas where it's worth to do a search on a higher resolution, so you don't waste your time on areas where there is nothing of interest.

    There are a number of more advanced techniques, but it's still worth to take a look at the basic chamfer matching, as it is the base of a large number of techniques.

    0 讨论(0)
  • 2021-02-05 12:34

    With the assumption that the objects are simple shapes, here's an approach using thresholding + contour approximation. Contour approximation is based on the assumption that a curve can be approximated by a series of short line segments which can be used to determine the shape of a contour. For instance, a triangle has three vertices, a square/rectangle has four vertices, a pentagon has five vertices, and so on.

    1. Obtain binary image. We load the image, convert to grayscale, Gaussian blur, then adaptive threshold to obtain a binary image.

    2. Detect shapes. Find contours and identify the shape of each contour using contour approximation filtering. This can be done using arcLength to compute the perimeter of the contour and approxPolyDP to obtain the actual contour approximation.


    Input image

    Detected objects highlighted in green

    Labeled contours

    Code

    import cv2
    
    def detect_shape(c):
        # Compute perimeter of contour and perform contour approximation
        shape = ""
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.04 * peri, True)
    
        # Triangle
        if len(approx) == 3:
            shape = "triangle"
    
        # Square or rectangle
        elif len(approx) == 4:
            (x, y, w, h) = cv2.boundingRect(approx)
            ar = w / float(h)
    
            # A square will have an aspect ratio that is approximately
            # equal to one, otherwise, the shape is a rectangle
            shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"
    
        # Star
        elif len(approx) == 10:
            shape = "star"
    
        # Otherwise assume as circle or oval
        else:
            shape = "circle"
    
        return shape
    
    # Load image, grayscale, Gaussian blur, and adaptive threshold
    image = cv2.imread('1.jpg')
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (7,7), 0)
    thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,31,3)
    
    # Find contours and detect shape
    cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        # Identify shape
        shape = detect_shape(c)
    
        # Find centroid and label shape name
        M = cv2.moments(c)
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])
        cv2.putText(image, shape, (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (36,255,12), 2)
    
    cv2.imshow('thresh', thresh)
    cv2.imshow('image', image)
    cv2.waitKey()
    
    0 讨论(0)
  • 2021-02-05 12:35

    These posts will get you started:

    • How to detect circles

    • How to detect squares

    • How to detect a sheet of paper (advanced square detection)

    You will probably have to adjust some parameters in these codes to match your circles/squares, but the core of the technique is shown on these examples.

    0 讨论(0)
提交回复
热议问题