Page 1 of 1

Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-26T10:28:49-07:00
by whugemann
I have a bunch of JPEG images steeming from a speed trap, which look like
Image
The above image shows a rectangular section taken from the original image with reduced resolution. The trick is that all images contain a quadrangle which spans around the licence plate and that is darker in colour, in order to keep the licence plate readable. The coordinates of its corner points are documented in an XML file which has the same name as the JPEG, i.e. there is always a pair of files: the JPEG and the measuring information.

I wonder whether there is a way to apply a contrast stretch only to the region of the quadrangle and another only to the outer region, in order to achieve an even brightness of the entire image.

I have to admit that this is a very specific problem, but the general question is whether there is a way to limit certain operations, say blurring, to a polygonial selection within the image. I think that nowadays we often have the situation that we have an image and a bunch of additional information that is either embedded in it or comes as a separate file. So I could think of a lot of problem statements that are related to this question.

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-26T10:45:05-07:00
by snibgo
"-mask" will do this. Windows script, applying the contrast stretch only to the outer part. I have deliberately not used the exact coordinates of the sub-image. To apply to only the inner part, negate the mask before use.

Code: Select all

"%IMG%convert" ^
  -size 400x329 xc:black ^
  -fill White ^
  -draw "rectangle 165,71 346,219" ^
  mask.png

"%IMG%convert" ^
  frame.jpg ^
  -mask mask.png ^
  -contrast-stretch 10%%x10%% ^
  +mask ^
  frameStr.png
The job could be done in a single convert statement.

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-26T11:04:42-07:00
by fmw42
You could also use -region http://www.imagemagick.org/script/comma ... php#region. It is easier than using -mask, but won't do the outer part. Using -mask as user snibgo suggested is more flexible, since you can negate the mask as needed to do the outside or the inside.

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-27T07:49:23-07:00
by whugemann
OK, -mask does the trick. I knew about -region, but that only allows to produce a rectangle AFAIK. But I was asking for an arbitrary quadrangle -- or, even more general, an arbitrary shape. The darker region in the example photograph may look like a rectangle, but it isn't exactly!

@Fred: You probably know it by heart: How would I do the same contrast stretch (say 2%x2%) for the inner and outer region of the shape in just one command?

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-27T08:29:52-07:00
by snibgo
I'm not Fred, who can probably give a better solution, but here's one way (Windows script):

Code: Select all

"%IMG684%convert" ^
  frame.jpg ^
  ( +clone -fill xc:black -colorize 100%% ^
    -fill White ^
    -draw "polygon 173,81 360,80 360,234 173,293" ^
    -write mask.mpr +delete ^
  ) ^
  -mask mask.mpr -contrast-stretch 2%%x2%% +mask ^
  ( mask.mpr -negate -write maskN.mpr +delete ) ^
  -mask maskN.mpr -contrast-stretch 2%%x2%% +mask ^
  out.png
You can put anything you like in the "-draw", including multiple polygons.
whugemann wrote:I wonder whether there is a way to apply a contrast stretch only to the region of the quadrangle and another only to the outer region, in order to achieve an even brightness of the entire image.
Achieving an even brightness is difficult, I think. If you want to match the grey tones on each side of the boundary, I think you would need to sample one or more points on each side, and do some action (perhaps "-compose Overlay -composite") to each area that equalised the grays.

EDIT: Sorry, I included "-blur x5" in that script, for some playing I was doing. Ignore it.

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-27T10:33:34-07:00
by fmw42
You can extract the points from your xml file. Then create a white mask by using -draw on a same size, say black background, to create a white filled polygon. Then that mask can be used for the outside and if negated, it can be used for the inside. User snibgo's code is about as efficient as it gets.

But I do not understand why you need to go to all this trouble if you are processing both the inside and outside with the same contrast-stretch, when you can do that directly. It only makes sense to me to use this if the contrast-stretch is different between the inside and outside. Do I misunderstand?

see
http://www.imagemagick.org/Usage/draw/#primitives

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-27T17:46:21-07:00
by anthony
Also see...

Masking (Write)
http://www.imagemagick.org/Usage/masking/#special_masks

and immediately after that on the same page...
Regions
http://www.imagemagick.org/Usage/masking/#regions

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-28T00:40:16-07:00
by whugemann
fmw42 wrote:You can extract the points from your xml file. Then create a white mask by using -draw on a same size, say black background, to create a white filled polygon. Then that mask can be used for the outside and if negated, it can be used for the inside. User snibgo's code is about as efficient as it gets.
Well, I already proceeded this way, drawing a polyline over the quadrangle for other purposes. I will possible present the DOS batch code on my Windows usage page.
fmw42 wrote: But I do not understand why you need to go to all this trouble if you are processing both the inside and outside with the same contrast-stretch, when you can do that directly. It only makes sense to me to use this if the contrast-stretch is different between the inside and outside. Do I misunderstand?
Although the contrast stretch has the same parameters, it is not the same operation, as the stretch boundaries are determined on the basis of the histogramms, which differ in both portions of the image.

I have just tested snibog's code and it is almost working. It changes the histogram in the outer portion, but not in the inner. I will surely find out why over Easter.

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-28T08:59:23-07:00
by snibgo
whugemann wrote:Although the contrast stretch has the same parameters, it is not the same operation, as the stretch boundaries are determined on the basis of the histogramms, which differ in both portions of the image.
Sadly, that's not true. My command should have exactly the same effect as ...

Code: Select all

"%IMG684%convert" ^
  frame.jpg ^
  -contrast-stretch 2%%x2%% +mask ^
  out.png
... because "-contrast-stretch" uses all the image pixels to calculate how to stretch. See the pages Anthony has linked to. The mask only limits which pixels are stretched.

My command is useful only for applying different stretches.

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-28T11:52:49-07:00
by whugemann
snibgo wrote: ... because "-contrast-stretch" uses all the image pixels to calculate how to stretch. See the pages Anthony has linked to. The mask only limits which pixels are stretched.
Hmm. This is not how I would expect a mask or selection to function :-(
If you use a selection or mask in Photoshop or Gimp, all functionality applies only to the selection, definitively including histogram corrections.

In my specific case, one could possibly use a region as an auxiliary tool, as the quadrangle ist almost rectangular. I will check if at least region makes histogramm corrections based on a limited area of the image.

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-03-28T11:55:02-07:00
by fmw42
The issue is that -mask is write mask and not a read mask. So snibgo's comments above are correct. In IM 7 there will be read masks.

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-04-08T01:47:11-07:00
by whugemann
I have just tried a solution based on -region. This basically works, as -region obvisously is what you call a "read mask", i.e. the histogramm corrections are based on the region selected. So I can "select" the darker region of the image, make the desired corrections and then come back to the outer part of the image. I could just use +region and perform a second histogramm correction on the entire image, but that would apply a second correction to the now already brightened inner rectangle, which is not desired.

A workaround is to disect the outer part in four regions, i.e. upper part, left + right of the quadrangle, lower part, and apply the histogramm corrections to those parts separately. In this case, the disection, however, becomes slightly visible, as the histogramm corrections turn out slightly different in the four "outer" parts of the image.

Is there any trick to select the outer part of a region or somehow fixate the boundaries of the histogramm corrections?

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-04-08T09:10:30-07:00
by fmw42
Do the histogram processing on the whole image to get the outside processing. Then use region on the original to do the rectangle. Then crop the rectangle and composite at the same location on the already background processed image.

Re: Contrast stretch for an arbitrary quadrangle

Posted: 2013-04-08T16:26:20-07:00
by anthony
Region could be regarded as both a read and write mask 8)

Though really it is not quite a read mask either. For example blurring a region will have different 'virtual-pixel' effects around the edge of the region, than the equivalent true read mask.

However for operations that do not involve area effects (contrast-stretch being such an example) a read mask is not needed, though can improve performance. Unfortunately something like contrast-stretch (or even auto-level), that first gathers information on pixel data, a read mask will have effect on that part of the operation. That is the read mask can ensure the calculated bounds of the stretch is limited to the actual pixels being stretch.

Getting up on my Soapbox...

With regards to regions... Something else that is also being looked at in IMv7 is for a 'virtual-pixel read mask', so that virtual-pixels can also be marked as 'unreadable', to operation that understand this.

This VP-read-mask would for example allow distort scaling to behave more directly like Resize, in that it ignores pixels outside the image proper. Something that the current -distort Resize method is essentially 'fudging' using a technique involving pixel blending properties of the alpha channel. Though it may mean that images with transparency may need to be distorted twice and results merged. The VP-read-mask would remove that need to fudge distort handling.