MATLAB Answers

How can you sum up all vectors from a quiver plot?

조회 수: 12(최근 30일)
Flint Marko
Flint Marko 2021년 8월 16일
댓글: Adam Danz 2021년 8월 17일
I am trying to figure out a way to sum up all of the vectors from a quiver plot. I am trying to quantify the gradient of an image. Currently, I have a quiver plot that has vectors for each pixel where each vectors is they are pointing from darkest(0) to lightest pixel(up to 255) in their vicinity, with the size of the arrow corresponding to how drastic the change is. For example a black pixel(0) neighboring a white pixel(255) would have a larger arrow than a black pixel(0) neighboring a grey pixel(~50).
How can the data extracted from [Gmag,Gdir] be used to show that there is a difinitive difference between an image with a gradient in a clear direction vs an image with no gradient and no clear direction? Additionally, can we sum the vectors to show one big arrow showing the angle in which the gradient is generally headed?

답변(2개)

Adam Danz
Adam Danz 2021년 8월 17일
편집: Adam Danz 2021년 8월 17일
This solution computes the vector sum of all quiver vectors in the test image and then computes the 95% confidence interval (CI) of the vector sum by randomly shuffling the pixels of the test image and computing the vector sum 1000 times. The 95% CI is the middle 95% of the distribution. This is the percential method and avoids using parametric tests which is a growing trend in many fields of science (see a list of articles at the bottom of this answer).
A plot is generated that shows (1) the test image with quiver arrows pointing to the neighboring pixel with the highest grayscale values, (2) an example of a shuffled image (the last bootstrapped image), and (3) the distribution of all bootstrapped vector sums which will form a gaussian centered at x=0 thanks to the Central Limit Theorm, the 95% confidence bounds, and a line showing the vector sum of the test image.
If the test has a non-random pattern of vector arrows, its vector sum will fall outside of the 95% confidence interval (see caveats below). The main idea is that shuffled images should have vector sums near 0 since the vectors should largely cancel each other out.
Caveats:
  1. There's probably a better, pre-established method used in fields that regularly compute this kind of analysis. The shuffled pixel bootstrap analysis is still a very good method of determining significant difference but the vector sum method may not be the best method - it's just something I thought of to address your question.
  2. Based on the description of your question, it sounds like you expect the gradient to be nearly unidirectional which will make this method more robust. If the darkest or lightest pixels are centered in the image and the vectors are all pointing inward or outward, they too will cancel out each other and the difference will not be significant. But that's what you would want given the description in your quesiton. As you can see, the test image I created nearly fits this description and is significantly graded but nearly misses the significance boundary.
% Generate test image for demo
I1 = imread('cameraman.tif');
Ir = imresize(I1, 1/32);
IrDbl = double(Ir);
I1Norm = IrDbl/double(intmax('uint8'));
% Compute vectors for test image
[u1,v1] = gradient(I1Norm,1,1);
[x,y] = meshgrid(1:size(I1Norm,1),1:size(I1Norm,2));
% vector sum for test image
I1Sum = sum(u1(:)+v1(:));
% Compute 95% bootstrapped confidence intervals
nBootStraps = 1000;
Ibsum = nan(1,nBootStraps);
rng('default') % for reproducibility - do not include in your implementation
for i = 1:nBootStraps
% Scramble image pixels
Itemp = reshape(I1Norm(randperm(numel(I1Norm))),size(I1Norm));
% Compute quiver components
[uTemp,vTemp] = gradient(Itemp,1,1);
Ibsum(i) = sum(uTemp(:)+vTemp(:));
end
% compute interval (percentile method)
alpha = 95;
prc = abs([0,100]-(100-alpha)/2);
CI = prctile(Ibsum,prc);
% is the image motion significantly different?
isSignificantlyDifferent = I1Sum < CI(1) || I1Sum > CI(2);
% Plot results
figure()
tiledlayout(2,2, 'Padding','compact','TileSpacing','compact')
ax1 = nexttile;
hold on
imshow(I1Norm) % main test image
axis tight
qh1 = quiver(x,y,u1,v1,1,'LineWidth',1);
title('TestImage')
ax2 = nexttile;
hold on
imshow(Itemp) %show the last bootstrapped shuffled image
axis tight
qh2 = quiver(x,y,uTemp,vTemp,1,'LineWidth',1);
title('Example of shuffled image')
linkaxes([ax1,ax2])
nexttile(1:2)
histogram(Ibsum,'DisplayName','VectorSums')
xline(CI(1),'DisplayName','LowBound');
xline(CI(2),'DisplayName','HighBound')
xline(I1Sum, 'm-', 'DisplayName','TestImage')
xlabel('VectorSum')
ylabel('Count')
title('Distribution of bootstrapped vector sums')
subtitle(sprintf('Significantly different = %.0f', isSignificantlyDifferent))
legend('Location','SouthOutside','Orientation','Horizontal')

Flint Marko
Flint Marko 2021년 8월 17일
Hello Adam, thank you for finding the time to give your suggestions. As you noted, I do expect the gradient to be relatively unidirectional with the images I want to analyze. However, the ROI's of the image will be circlular in nature and have varying degrees of gradients.
I am mostly interested in: 1. Determining and visually showing the direction of that gradient through a vector arrow and 2. Quantitatively showing that the gradient images (Left) are indeed unique when compared to my control image (Right). I have attached an example of a circle with a unidirectional gradient (Left) and one without a directional gradient (Right). The method you showed here might be promising for quantitatively comparing each picture, but I am having troubles getting them to run with my image:
Error using gradient>parse_inputs (line 184)
The number of spacing inputs must match the number of array dimensions.
Error in gradient (line 48)
[f,ndim,loc,rflag] = parse_inputs(f,varargin);
Error in Bootstrap (line 7)
[u1,v1] = gradient(I1Norm,1,1);
One additional issue I have run into is avoid counting the pixels of the background (in this case white(255)). My images are also usually 1024x1024.
  댓글 수: 1
Adam Danz
Adam Danz 2021년 8월 17일
This version of the question differs from the original question. The original question describes working with pixels and shades of gray. It also has become clear that you want to compare two specific images. Unfortunately I've already invested a significant chunk of time answering the wrong question and I haven't got the time today to do that again.
Based on the image, I don't know how the quiver arrows are created. Are the dots what you refer to as pixels?
If you want to do an actual pixel analysis you could use imresize to spatially average the images within a grid and the grayscale values would be a measure of dot density (this is demonstrated in line 2 of my answer). Then you could produce the quiver arrows (also shown in my answer). A vector sum of arrows from an image with an appoximately unidirectional gradient will be large and in the direction of the gradient but the vector sum of the the 2nd image will be small and in an unpredictable direction.
Or, instead of doing a vector sum, you could use [theta,rho]=cart2pol(U,V) to get the direction and magnitude values of each quiver arrow. If the goal is to determine of the gradient of the two images differ you could compare the distributions of theta angles (use histogram(theta) to visualize the distributions). Then you could choose a statistic that determines if two distributions are significantly different.

댓글을 달려면 로그인하십시오.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by