Identify and Crop Coin from Image

I am trying to create a process that will crop the coin from the images in this folder:

https://drive.google.com/drive/folders/1n6WOWrG0gqVgCtfX79rtzJH64bcHM-G8?usp=sharing

I tried to following this link but wouldn’t work for me. How to find the circle in the given images using opencv python (hough circles )? - Stack Overflow

There’s a ‘t’ missing in that link: it should read … -python-though-circles

Poorly worded by me - the link works but I couldn’t get the code to work for my image.

Hi @rob26r,

Since the background color is easily distinguishable from the color of the quarter, you don’t need a very complex script to identify the needed cropping boundaries.

The following is a Python Mode for Processing script that finds and outputs the x and y values for those boundaries. It was tested using the template quarter image from the link that you provided. The Python code is below. Note the following line, which outputs the coordinates to the console:

print(left, right, top, bottom)

The output for the template quarter was:

(437, 1799, 139, 1533)

Here’s the code, which must be executed in Processing Python Mode:

template = None
scaler = 1
def setup():
    global template
    size(3200 / scaler, 1800 / scaler)
    template = loadImage("Template_Qtr.jpg")
    # print(template.width, template.height)
    noLoop()
def draw():
    background(0)
    margin = 40 # for avoiding the border color of the image
    red_bound = 160 # for identifying the background color of the image
    image(template, 0, 0, template.width / scaler, template.height / scaler)
        
    # find left boundary of coin
    done = False
    for x in range(margin, width - margin):
        for y in range(margin, height - margin, 1):
            p = get(x, y)
            if red(p) < red_bound:
                done = True
            if done:
                break
        if done:
            left = x
            break
        
    # find right boundary of coin
    done = False
    for x in range(width - margin, margin, -1):
        for y in range(margin, height - margin):
            p = get(x, y)
            # d = dist(red(p), 230, green(p), 110, blue(p), 2)
            if red(p) < red_bound:
                done = True
            if done:
                break
        if done:
            right = x
            break

    # find top boundary of coin
    done = False
    for y in range(margin, height - margin, 1):
        for x in range(margin, width - margin, 1):
            p = get(x, y)
            # d = dist(red(p), 230, green(p), 110, blue(p), 2)
            if red(p) < red_bound:
                done = True
            if done:
                break
        if done:
            top = y
            break
    # find bottom boundary of coin
    done = False
    for y in range(height - margin, margin, -1):
        for x in range(margin, width - margin, 1):
            p = get(x, y)
            # d = dist(red(p), 230, green(p), 110, blue(p), 2)
            if red(p) < red_bound:
                done = True
            if done:
                break
        if done:
            bottom = y
            break
    # display boundary data
    print(left, right, top, bottom)

With some additional work, you could automate the cropping of the image, and the saving of the results. If you give it a try and post your code, we can make suggestions.

The following links may be helpful to you:

EDITED on April 12, 2022 to change the value of red_bound to 160.

Ya’ know, I did think wait, what!??..

My bad; I should have guessed that nobody on this Forum could be that dumb - sorry dude :slightly_smiling_face:

Note that in each of the images, the bottom of the coin casts a shadow onto the background. For this reason, it is advantageous to use a lower value for the red_bound variable to find the bottom of the coin. Accordingly, the code that finds the bottom of the quarter should be revised to begin as follows:

    # find bottom boundary of coin
    # reassign red_bound to account for the shadow
    red_bound = 120

With this revision, the output is:

(437, 1799, 139, 1502)

I’m fairly new to Python. Sadly, I don’t even know what Processing Python Mode is.

Not sure if this is possible - can I take the code you provided and translate it so I can run it in Python?

Thanks.

It is Python code, but it in its current form, it can only be executed in a Python Mode for Processing environment. The code calls functions that are particular to that context, so porting it for use outside that environment would require substantial rewriting.

The example was written for the special purpose of identifying cropping boundaries for the examples of coin images that you provided. With some additional refinement, it might be useful for automating the cropping of your larger collection of images.

If, however, you plan to perform more substantial additional work on the coin images over the long term, it would be a good idea to do some further investigation regarding Python packages for working with images, or even packages written for other languages that you either know or would be interested in learning. What is available for Python includes the following: