Centering Annotations within a Square/Rect.

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?".
don

Centering Annotations within a Square/Rect.

Post by don »

Hello,

I'm trying to find out if the following scenario is possible (using the perl mod).

I've got an image with 300 squares and rectangles all mixed in with one another. I place an annotation in one of the squares based the x/y's of a pixel within that square. Is it possible to 'gravity => Center' the annotation without entering the xy's of the exact center?

TIA

Don
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Centering Annotations within a Square/Rect.

Post by fmw42 »

don

Re: Centering Annotations within a Square/Rect.

Post by don »

Thanks for the reply.

I've gone over that page a few times and still cannot find an answer for what I'm looking for.

Let me elaborate a bit more....

I get maps with about 300-400 lots on them. The only thing on the maps are the perimeter lines for each lot. Also, each lot is a different size/shape (for the most part). I'm trying to write a perl script that will display the empty map to a user and allow them to click on each lot and give it a label. The problem is that these users will most likely never choose the true "center" of a lot, so when all of the results are displayed it doesn't look so good.

The goal here is to get the text to center/align correctly within each lot based on the x-y coor's that the user clicks on. I have everything else working except I can't figure out how to align the text based on the user selection.

Sorry for my lack of terminology on this one. I've been programming for years but this is the first time that I've had to do mass image manipulation.

Thanks again for the help.

Don
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Centering Annotations within a Square/Rect.

Post by fmw42 »

you probably have to use label: (or caption:) to have it create an image just large enough to hold the text. then figure out how big that image is. then compute the offset from the middle to the upper left. then use annotate to put the text where you want relative to the user supplied coordinates offset by the x,y offset computed from the label: result.

It is typical when doing text to create the minimum image size for the text once from label: to get the size, then use that with -annotate in a second pass.

You may not have to actually save the image from label:.

convert -verbose label:"This Is A Test" null: 2>&1

returns:
label:This Is A Test=>This Is A Test LABEL 74x15 74x15+0+0 16-bit DirectClass 0.340u 0:02
label:This Is A Test=> LABEL 74x15 74x15+0+0 16-bit DirectClass

So from this you can extract the image size it would make as 74x15
don

Re: Centering Annotations within a Square/Rect.

Post by don »

Thanks for the reply. I'll look more into your suggestions and post my findings.

I thought there would be some ability to find the edges of each lot/square/rectangle and center based on that (since floodfill works great).

Don
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Centering Annotations within a Square/Rect.

Post by anthony »

Actually NO. only by finding the location of the center of the rectange relative to the center of the image ;-(

The relative problem is because IM currently does not separate gravity positioning from justification of the text.


the easiest way I think may be to create a label: image of the annotation the same size as the rectangle, with -gravity center to center it. than overlay that label alining the top left corner.

For example suppose the rectangle is located at 100x50+200+50 For example...
the text can be centred in that rectangle using...

Code: Select all

   convert logo:  -gravity center \
                -background cyan  -size 100x50 -page +200+50 -pointsize 12 label:"Some Text" \
                -flatten    image_result.png
Note I used -page and -flatten in the above as it is not gravity effected, so I can leave it set.
Replace the -background color 'cyan' to 'none' to preserve the rectangles original color. and duplicate the middle line as any times as you need.

if you leave out -pointsize, the text will auto-size to best fit the rectangle!
if you also replace label: with caption; it will also word wrap with best-fit

WARNING: before IM v6.5.2-4 (quite recent actually) the -pointsize would have been ignored in the above!!! In that case use this line instead.

Code: Select all

     \( -background cyan -page +200+50 -pointsize 12 label:"Some Text" -extent 100x50 \) \ 
Unless of course you want best-fit, in which case use the above and remove the -pointsize setting

ERROR ERROR ERROR; the above found a bug in that when -page was put in parenthesis it effected the offset position of logo; as well! I have reported this problem, on the bigs forum. Because of this my fix for 'older IMs' will not work -- sorry...
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
don

Re: Centering Annotations within a Square/Rect.

Post by don »

Hi Anthony...

Thank you very much for your hints on this one. The problem is that there are 300 squares and rectangles on each page, nearly all of which are different sizes and orientations. This makes it impossible for the script to know the exact size of each square/rectangle.

I thought maybe it would be possible pass PerlMagick x/y coor's of a pixel within each square/rectangle and then it could center based on the border/edges of that square/rectangle. If FloodFill can find the edges/borders of a square/rectangle based on any x/y coor's within that square, then it seems like this would be possible.
don

Re: Centering Annotations within a Square/Rect.

Post by don »

Actually I had another thought...

Is there any way to just query the geometry of a shape on an image, simply based on the x/y of a pixel within the shape?

If I can do that then I can get the script to do the rest.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Centering Annotations within a Square/Rect.

Post by anthony »

don wrote:I thought maybe it would be possible pass PerlMagick x/y coor's of a pixel within each square/rectangle and then it could center based on the border/edges of that square/rectangle. If FloodFill can find the edges/borders of a square/rectangle based on any x/y coor's within that square, then it seems like this would be possible.
Now that is a different matter. You need to somehow determine the size and location of each of those rectangles!!!!

This is known as image segmentation, and it can be done, especially if you can guarantee that each rectangle does not overlap any other rectangle. Better still their is some separation between each of the rectangle, which somehow differ from the background of the image.

All you then need to a automatic way of determining the location of the top left corner. then from that you can mask out and get the size of each rectangle. If these are segmented into image layers, you can then deal with each layer as a separate image for annotation, and then 'flatten' or 'merge' them all back together.

If you want to try this, please do, and let us know. If you want further help, than a small example of your problem image will be needed.
Actually I had another thought...

Is there any way to just query the geometry of a shape on an image, simply based on the x/y of a pixel within the shape?

If I can do that then I can get the script to do the rest.
You may like to look at a generate image segmentation script that was already developed...
http://www.imagemagick.org/Usage/scripts/segment_image
This script works with a mask of pure black and white colors and generates one image for each separate region found, including the background.
See discussion at viewtopic.php?f=1&t=11705
The discussion went further by trimming the images which will get you your 'bounds'.

This is one script I'd like see implemented in the core IM library, perhaps as part of a collection of 'segment image' methods.


As you are dealing with rectangles, a much faster method of bounds determination should be posible, but may require it to be performed from an API.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
don

Re: Centering Annotations within a Square/Rect.

Post by don »

Hi Anthony,

Thanks for the reply. I think I've found a way to do this one part with Rmagick with it's pixel.fcmp feature. The only problem is that I've never used Ruby so I'm at a large curve there.

I'll look into the script you mentioned and see if I can do this a bit more natively.

Thanks again for the help,

Don
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Centering Annotations within a Square/Rect.

Post by anthony »

With an API you would just read the image into memory once, do your calculations and just do the job. No problems, dramas or repeated commands.

It is only scripts that would have problems in requiring multiple commands.

If you like to do it in Ruby, then by all means. Same goes for PHP imagaick, or PerlMagick.
Lots of options.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
don

Re: Centering Annotations within a Square/Rect.

Post by don »

Hi Anthony,

The main script is perl and I'm using PerlMagick with it. The problem is that I didn't find a feature like pixel.fcmp in the perl API. I would much rather not use ruby and do it in perl, but that's not looking like it's in the cards.

Out of curiosity, why would Rmagick have this feature and not PerlMagick?

Thanks again for the help.

Don
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Centering Annotations within a Square/Rect.

Post by anthony »

I do not know what pixel.fcmp does so I can't tell you.

Their are some things in Rmagick that was implements in the ruby side of the API. For example polaroid was original developed in this way before being incorporated into the core library, but I doubt this is one of them.

As all Command line operators should be available in Perl Magick, somehow, it is just a matter of finding the perl API syntax you need.

So what does it do?
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
don

Re: Centering Annotations within a Square/Rect.

Post by don »

Hi Anthony,

I see what you mean. With pixel.fcmp you can specify a pixel via the x/y and then see if it is whatever color(or nears the "fuzz" margin if specified). I can write a routine in my perl script that will pass the x/y on to a ruby script which performs the pixel.fcmp, and then returns true or false appropriately. Perl will keep querying the ruby script until it knows the borders of the north, south, east, and west points from the initial pixel that was specified. Then it will calculate the center pixel and size of each shape.

Of course, that would be in a semi-perfect world. Here are the two caveats that I'm running into.

1. I don't know Ruby.

2. When I install Rmagick it forces me to install a much older version of imagemagick. This version of Imagemagick does not have the ActivePerl module option during installation and it is so old that I cannot find a standalone Perlmagick version for it.

I've gone over the Perlmagick Doc's at least 10 times and cannot find anything, or any combination of things to perform this function. If you know of something that could help here I'd sure appreciate it.

Thanks,
Don
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Centering Annotations within a Square/Rect.

Post by fmw42 »

are you just trying to compare some color to the color at some pixel value in an image?

get dimensions of rose: image:
identify rose:
rose:=>ROSE ROSE 70x46 70x46+0+0 8-bit DirectClass 9.45kb

size is 70x46, so center is at 35,23

check the color of the center pixel in the rose image:
convert rose:[1x1+35+23] txt:
# ImageMagick pixel enumeration: 1,1,255,rgb
0,0: (246, 47, 55) #F62F37 rgb(246,47,55)

compare that color to the value at the center of the rose image:
compare -metric rmse \( -size 1x1 xc:"rgb(246,47,55)" \) rose:[1x1+35+23] null:
0 (0)

so it exactly matches as the rmse value is zero

but if we compare pure red to the center pixel in the rose image, we get

compare -metric rmse \( -size 1x1 xc:red \) rose:[1x1+35+23] null:
10817.4 (0.165063)

so we see that they differ by an rmse of .165063 or 16.5%
Post Reply