Search code examples
pythonopencvimage-processingdeep-learningartificial-intelligence

Image Processing - How to count objects on an image (stacked leathers)


I want to count leathers on a stacked leather image, any image processing help is appreciated.

After below some python codes, I realized my code is not a robust method, it can totally change depending on function parameters values and input images. I need a robust method to handle this problem. Thank you for your efforts.

import cv2
path= r'image.bmp'
im = cv2.imread(path)
im = cv2.resize(im, (640,480), interpolation = cv2.INTER_AREA)
cv2.imwrite('savedImage2.jpg', im) 
im = cv2.GaussianBlur(im, (7,7), sigmaX=31) 
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) 
im = cv2.inRange(im, 50, 90)
cv2.imshow('image', im)
cv2.waitKey(0) 
cv2.destroyAllWindows()

original image1-before

(leather count=8 in image, truth value=8

processed image1-after

original image2-before

(leather count=8 in image, truth value=8)

processed image2-after


Solution

  • This is a simple idea and certainly not suitable for all test_cases. Note that the more time you spend, the more images you review and the more you read the image processing tools; You will achieve better results and find better solutions. So this is not something that you can get the best possible answer in a few minutes. The next issue is environmental conditions. The less you change the environment, the less error you will have.

    import cv2
    import sys
    import math
    import numpy as np
    
    # Load image
    org = cv2.imread(sys.path[0]+'/1.jpg')
    im = org.copy()
    H, W = im.shape[:2]
    
    # Make a clean binary image
    im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    im = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
    im = cv2.medianBlur(im, 5)
    
    # Slice top of the image
    org = org[0:20, 0:W]
    im = im[0:20, 0:W]
    H, W = im.shape[:2]
    
    # Clean lines like a barcode
    im = cv2.GaussianBlur(im, (1,31), 31)
    im=cv2.threshold(im,127,255,cv2.THRESH_BINARY)[1]
    cv2.rectangle(im, (0, 0), (W, H), 255, 3)
    
    # Find contours
    cnts, _ = cv2.findContours(im, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    for cnt in cnts:
        x, y, w, h = cv2.boundingRect(cnt)
        if w < W:
            cv2.rectangle(im, (x, y), (x+w, y+h), (0, 255, 0), 1)
    
    # Count lines
    lines = len(cnts)-1
    num = math.ceil(lines/3)
    print(num)
    
    # Save and show output
    im=cv2.cvtColor(im,cv2.COLOR_GRAY2BGR)
    cv2.imwrite(sys.path[0]+'/1_.jpg',np.vstack((org,im)))
    

    Note that the edges of your two test_cases are different and appear to be of two different types. So it is normal that you can not handle all the different samples with a simple algorithm. Examine the ideas, change the parameters, add new ideas until you finally get the desired result.

    Output image:

    enter image description here

    Output number is 8 for this testcase.


    Finally, I think if you can put the pieces together cleanly (close the gap between them) and always shoot from a fixed angle with a fixed camera and the same amount of light, you might be able to achieve a better result.