I’m new to mathematica and want to learn more about this powerful tool.

So I want to generate a vector map from image showing how fast some values goes from lighter to darker colors. I found function GradientOrientationFilter very useful, in particular first “neat example” from link is almost what I’m looking for. Except the fact that orientation of the vector should be flipped by Pi if the tale located in brighter than arrowhead area.

I’m working with gray scaled data images. And want to get something like that with exception that vectors should point from light to dark area

So here is a slightly altered example from that link

dims = ImageDimensions[img];

radius = 3;

dirs = ImageData[GradientOrientationFilter[img, radius]];

magnitudes = ImageData[GradientFilter[img, radius]];

ar1 = Join[Partition[Flatten[dirs], 1],

Partition[Flatten[magnitudes], 1], 2];

ar2 = Partition[ar1, First[dims]];

That’s all I got so far, rest of the code remains unchanged compared with neat example:

orientations =

MapThread[#1 {-Sin[#2], Cos[#2]} &, {magnitudes, dirs}, 2];

Show[img,

ListVectorPlot[

MapIndexed[{{#2[[2]], dims[[2]] – #2[[1]]}, #1} &,

orientations, {2}], VectorColorFunction -> (Yellow &)]]

As you can see I made a list ar2 in which elements of the highest level have values for orientation and magnitude together, but here I stuck. I don’t know how to go through this ar2 list (which for example have values

{{A11, B11}…{An1, Bn1}

…

{A1m, B1m}…{*Anm, **Bnm}}

where A is orientation, B is magnitude, and nm are XY indexes of pixels) and compare some element kl of image with element in the end of the vector (somehow recognized from Akl and Bkl) and depending on comparison of kl with this element either change Akl or leave it as is.

I’m apologizing for confusing explanations and rely on your help. Thank you.

=================

I just realized that I should use for B not magnitude for comparison but actually raw image data, something like ar1 = Join[Partition[Flatten[dirs], 1], Partition[Flatten[ImageData[img]], 1], 2]

– Yury

Oct 8 at 17:52

=================

1 Answer

1

=================

I don’t think GradientOrientationFilter can do what you want: It returns angles between -Ï€/2 .. Ï€/2 – i.e. no direction information.

The easiest way is probably to use DerivativeFilter to generate the x/y derivatives directly.

I’ve slightly modified your test image:

img = Image[

RotateLeft[

Rescale[DiamondMatrix[20,

70] + .2 RandomReal[NormalDistribution[], {70, 70}]], {5, 10}]]

Avoid symmetric test images when you can – otherwise you won’t notice subtle errors where you swap x/y, flip a sign etc. and spend hours later re-testing everything.

To get the derivatives in x/y direction (i.e. the components of the gradient vectors), you can simply use:

gy = DerivativeFilter[img, {1, 0}, 3];

gx = DerivativeFilter[img, {0, 1}, 3];

Convert those to the input format for ListVectorPlot:

dims = ImageDimensions[img];

gradientVectors = Table[

{{x, y}, {ImageValue[gx, {x, y}], -ImageValue[gy, {x, y}]}},

{x, 0, dims[[1]], 5}, {y, 0, dims[[2]], 5}];

(The – sign in front of the y gradient component is because of the subtle distinction between coordinates and indices in Mathematica. It’s annoying, but you get used to it.)

And display the result:

Show[img,

ListVectorPlot[gradientVectors, VectorColorFunction -> (Yellow &)],

ImageSize -> 400]