How to crop along a yellow frame

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
Jstar
Posts: 6
Joined: 2019-08-29T18:31:09-07:00
Authentication code: 1152

How to crop along a yellow frame

Post by Jstar »

We captured thousands of pictures of an object. That object had to be placed within a yellow frame, so that it does not touches the yellow frame.

I wanted to crop exactly the picture at that frame, but the frame moved over the time and even tilted slightly. I need a smarter way to crop.

Some notes. The frame is about 6x6 cm and the yellow frame is about 1.5 cm thick. The object is about 4x4 cm

I want to scan the picture to find the inner corners of the frame. The background is green, the frame is yellow. When the line changes from only green to yellow we start to find the line which gets interrupted by green - we are now at a line which sees the inner part of the frame. The first line where a yellow pixel is missing in the line, is a corner. Further scanning would reveal the next corners, just by interpreting where the green dot appears in the yellow line. In a perfected aligned frame the left and right corner would be found at once.

When I got these 4 corners, I want to crop the picture accordingly.

A python program captures the pictures in the first place. It would be great if we could find a way to crop it before it would be saved.

How can I do that?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to crop along a yellow frame

Post by fmw42 »

It would help considerably if you post an example image to some free image hosting service and put the URL here. Also please always provide your exact ImageMagick version and platform, since syntax may vary.

Units of inches are not helpful for raster images. Pixels are what are important.

There are a number of ways to perhaps do what I think you may want. But having an example image to see and use for testing and demonstration would be best.
Jstar
Posts: 6
Joined: 2019-08-29T18:31:09-07:00
Authentication code: 1152

Re: How to crop along a yellow frame

Post by Jstar »

Thanks for helping.

I put a sample picture at https://bc.elmit.com/john/test1.jpg
The picture size is 3280x2464 pixels
Within that picture is a yellow outer frame 1812x1812 pixels
The inner frame is 1350x1350 pixels, that gives a thick yellow line of 240 pixels.
Within this inner square is the target object.

We instructed the worker to place the object mostly centered within the yellow frame. We want to get a picture of the object only (couture) or a square within the yellow frame.

How can I get this picture? Would be nice if we could remove the green background to alpha and save it to png then.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to crop along a yellow frame

Post by fmw42 »

Here is one way to do that. Convert the image to binary where yellow becomes white and the rest becomes black. Then flood fill the outer black area with white. Then get the bounding box of the largest black region, which corresponds to the center area inside the yellow border. Then crop to that bounding box. Then optionally do a inner trim to remove all the excess yellow border. I have save the result before and after the inner trim.

Input:
Image

Unix Syntax:

Code: Select all

cropvals=$(convert test1.jpg -fuzz 10% -fill white -opaque "rgb(218,214,63)" \
-fill black +opaque white -fill white -draw "color 0,0 floodfill" -alpha off -type bilevel \
-define connected-components:verbose=true \
-connected-components 4 null: | grep "gray(0)" | head -n 1 | awk '{print $2}')

convert test1.jpg -crop $cropvals +repage -write test1_result1.jpg \
-fuzz 10% -define trim:percent-background=0% -trim +repage test1_result2.jpg
Image

Image

Here is a way to do it with just multiple trims and morphology to close some small holes. It is similar in processing to a binary pattern and then trimming.

Code: Select all

cropvals=$(convert test1.jpg -fuzz 10% -fill white -opaque "rgb(218,214,63)" \
-fill black +opaque white -fill white -draw "color 0,0 floodfill" -alpha off \
-morphology close disk:3 -trim \
-bordercolor white -border 1 \
-define trim:percent-background=0% -trim \
-format "%wx%h+%O" info:)
convert test1.jpg -crop $cropvals +repage test1_result3.jpg
Image
Jstar
Posts: 6
Joined: 2019-08-29T18:31:09-07:00
Authentication code: 1152

Re: How to crop along a yellow frame

Post by Jstar »

Thank you very much. I learned a lots with your solution.

I will pack it into a loop to crop my 15,000 pictures.
Jstar
Posts: 6
Joined: 2019-08-29T18:31:09-07:00
Authentication code: 1152

Re: How to crop along a yellow frame

Post by Jstar »

I tried the first suggestion, by creating a file 1.sh

Code: Select all

#!/bin/bash

cropvals=$(convert test1.jpg -fuzz 10% -fill white -opaque "rgb(218,214,63)" \
-fill black +opaque white -fill white -draw "color 0,0 floodfill" -alpha off -type bilevel \
-define connected-components:verbose=true \
-connected-components 4 null: | grep "gray(0)" | head -n 1 | awk '{print $2}')

convert test1.jpg -crop $cropvals +repage -write test1_result1.jpg \
-fuzz 10% -define trim:percent-background=0% -trim +repage test1_result2.jpg
When I run that command, I get:

Code: Select all

convert-im6.q16: invalid argument for option `-crop': +repage @ error/convert.c/ConvertImageCommand/1184.
convert --version

Code: Select all

Version: ImageMagick 6.9.7-4 Q16 x86_64 20170114 http://www.imagemagick.org
Copyright: © 1999-2017 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP 
Delegates (built-in): bzlib djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png tiff wmf x xml zlib
What did I do wrong?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to crop along a yellow frame

Post by fmw42 »

Your version may be buggy or too early for connected components. I get the same error when using IM 6.9.7.4. So try to upgrade and try it again. It works fine for me on IM 6.9.10.63 Q16 Mac OSX.
Jstar
Posts: 6
Joined: 2019-08-29T18:31:09-07:00
Authentication code: 1152

Re: How to crop along a yellow frame

Post by Jstar »

Thanks a lot for helping me.

I could still not manage to install it workable on my Linux machine. Luckily I got a MacBook Pro and have successfully installed here ImageMagic (takes a long time to install).

I use now 3 pictures from
https://bc.elmit.com/john/test1.jpg
https://bc.elmit.com/john/test2.jpg
https://bc.elmit.com/john/test3.jpg

I applied these two scripts with the responds underneath:

Code: Select all

#!/bin/bash

cropvals=$(convert test1.jpg -fuzz 10% -fill white -opaque "rgb(213,207,49)" \
-fill black +opaque white -fill white -draw "color 0,0 floodfill" -alpha off -type bilevel \
-define connected-components:verbose=true \
-connected-components 4 null: | grep "gray(0)" | head -n 1 | awk '{print $2}')

convert test1.jpg -crop $cropvals +repage -write test1_result1.jpg \
-fuzz 10% -define trim:percent-background=0% -trim +repage test1_result2.jpg

#

cropvals=$(convert test2.jpg -fuzz 10% -fill white -opaque "rgb(213,207,49)" \
-fill black +opaque white -fill white -draw "color 0,0 floodfill" -alpha off -type bilevel \
-define connected-components:verbose=true \
-connected-components 4 null: | grep "gray(0)" | head -n 1 | awk '{print $2}')

convert test2.jpg -crop $cropvals +repage -write test2_result1.jpg \
-fuzz 10% -define trim:percent-background=0% -trim +repage test2_result2.jpg

#

cropvals=$(convert test3.jpg -fuzz 10% -fill white -opaque "rgb(213,207,49)" \
-fill black +opaque white -fill white -draw "color 0,0 floodfill" -alpha off -type bilevel \
-define connected-components:verbose=true \
-connected-components 4 null: | grep "gray(0)" | head -n 1 | awk '{print $2}')

convert test3.jpg -crop $cropvals +repage -write test3_result1.jpg \
-fuzz 10% -define trim:percent-background=0% -trim +repage test3_result2.jpg
./1.sh
convert: geometry does not contain image `test3_result1.jpg' @ warning/attribute.c/GetImageBoundingBox/247.
(base) Ronalds-MBP:Downloads ronaldwiplinger$ ./2.sh
convert: geometry does not contain image `test3.jpg' @ warning/attribute.c/GetImageBoundingBox/247.
convert: geometry does not contain image `test3.jpg' @ warning/transform.c/CropImage/666.
(base) Ronalds-MBP:Downloads ronaldwiplinger$ ./1.sh
convert: geometry does not contain image `test3_result1.jpg' @ warning/attribute.c/GetImageBoundingBox/247.

Code: Select all

#!/bin/bash

cropvals=$(convert test1.jpg -fuzz 10% -fill white -opaque "rgb(218,214,63)" \
-fill black +opaque white -fill white -draw "color 0,0 floodfill" -alpha off \
-morphology close disk:3 -trim \
-bordercolor white -border 1 \
-define trim:percent-background=0% -trim \
-format "%wx%h+%O" info:)
convert test1.jpg -crop $cropvals +repage test1_result3.jpg

#

cropvals=$(convert test2.jpg -fuzz 10% -fill white -opaque "rgb(218,214,63)" \
-fill black +opaque white -fill white -draw "color 0,0 floodfill" -alpha off \
-morphology close disk:3 -trim \
-bordercolor white -border 1 \
-define trim:percent-background=0% -trim \
-format "%wx%h+%O" info:)
convert test2.jpg -crop $cropvals +repage test2_result3.jpg

#

cropvals=$(convert test3.jpg -fuzz 10% -fill white -opaque "rgb(218,214,63)" \
-fill black +opaque white -fill white -draw "color 0,0 floodfill" -alpha off \
-morphology close disk:3 -trim \
-bordercolor white -border 1 \
-define trim:percent-background=0% -trim \
-format "%wx%h+%O" info:)
convert test3.jpg -crop $cropvals +repage test3_result3.jpg
./2.sh
convert: geometry does not contain image `test3.jpg' @ warning/attribute.c/GetImageBoundingBox/247.
convert: geometry does not contain image `test3.jpg' @ warning/transform.c/CropImage/666.

1. I don't understand the messages the script gives me.
2. test1_result1.jpg, test1_result2.jpg, test1_result3.jpg are ok, although yellow frame still there
3. test2_result1.jpg, test2_result2.jpg, test2_result3.jpg are ok, although yellow frame still there
4. test3_result1.jpg, test3_result2.jpg, test3_result3.jpg are completely wrong.

How can I get test3 to work? We need to FIND the yellow frame first to crop within it.
Also for the other tests, we should be a few pixels (10 for testing) within the yellow frame to make sure the yellow frame is not in the picture.
In a second run, I might crop the pictures, depending on their size to a common standard size. Like get the info of all pictures in a directory and find the smallest size and crop to that size all pictures. That can only be done after the pictures have been prepared with above procedure.

BTW., does ImageMagic work on a Raspberry 4 ???
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to crop along a yellow frame

Post by fmw42 »

I believe the messages are saying that it has cropped the image to nothing.

Your third image does not conform to the assumptions that you have a full rectangular frame about the region you want to crop.

You may have to adjust the rgb color and the fuzz value to customize for each image.

To trim 10 pixels on each side, add -shave 10x10.
Jstar
Posts: 6
Joined: 2019-08-29T18:31:09-07:00
Authentication code: 1152

Re: How to crop along a yellow frame

Post by Jstar »

Coming back to the original post, how do I find the yellow frame?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to crop along a yellow frame

Post by fmw42 »

This works for me with test1 and test3. I did not check test2.

I added a second color for the other color in the yellow border region that is more whitish. I also increased the fuzz value to 15% and replace -morphology close with connected components processing to remove small regions in the outside of the yellow rectangle.

Code: Select all

cropvals=$(convert test3.jpg -fuzz 15% -fill white -opaque "rgb(210,213,182)" -fill white -opaque "rgb(218,214,63)" \
-fill black +opaque white -fill white -draw "color 0,0 floodfill" -alpha off \
-define connected-components:mean-color=true \
-define connected-components:area-threshold=1000 \
-connected-components 4 -trim \
-bordercolor white -border 1 \
-define trim:percent-background=0% -trim \
-format "%wx%h+%O" info:)
convert test3.jpg -crop $cropvals +repage test3_result.jpg

Post Reply