How to Stitch 25 images with different dynamic range

13 views (last 30 days)
Hi all,
Actually the question about how to take care of already stitched picture. I don't have any questions about the stitched process itself, I know how to do it. However after I do stitch I see the transition between the pictures. I would like to make a smooth transition between the pictures (see red arrows).
Every picture has 768X768 pixels. Every picture has a different dynamic rangle. So first of all I'd like to bring all the pictures to the same dynamic range, then to make slope compenstation on each picture and maybe then to stitch all of them. See the picture above one of the 25 pictures. I did mesh (X,Y,Z) and turned around this picture to show you the slope. I'd like to remove that slope.
I saw in one of the topics (https://www.mathworks.com/matlabcentral/answers/86498-how-to-blend-image) Image Analyst suggested to "You can use conv2() to blur the edge zone of the stitched pair, or you can stitch with a weighted average so that each edge has a ramp where it goes from full strength to zero." But how exactly to do this? Can you give me some example how to do it?
Here I attached 2 matrices for example to show you the slope and different dynamic ranges between them. So I'd like to bring all the matrices I have (25) to the same dynamic range and make slope compensation of each matrix I have.
Thank you very much.
P.S. If you want to stitch these two matrices you should put them as following:

Answers (3)

Bjorn Gustavsson
Bjorn Gustavsson on 26 Jan 2021
You could do something like this to level the regions:
dI = mean(Im(row_above,:)-Im(row_above+1,:)); % Perhaps median works better, depends on intensity variance
Im(1:row_above,:) = Im(1:row_above,:) - dI/2;
Im(row_below:end,:) = Im(row_below:end,:) + dI/2;
Then you simply have to step through all the seams to level the entire image. You should also keep track of all the dIs to know where the absolute intensity-correction goes.
HTH
  4 Comments
Dimani4
Dimani4 on 27 Jan 2021
Edited: Dimani4 on 27 Jan 2021
Thank you Bjorn.
Yes, exactly 5 rows of images (actually 5X5 5 rows, 5 columns).Each picture is 768X768pixels
See the results I did according your idea.
Take a look at the results.
Here is without your suggestion:
Here zoomed region
Here is with your suggestion (with median):
And here is the full stitching:
Bjorn Gustavsson
Bjorn Gustavsson on 27 Jan 2021
OK, so your spiky higher-intensity-regions vary much between the sub-images, while the smoother low-intensity-bands are reasonably similar. After looking at the 2 matrices in your files it is not exactly clear to me what you want to achieve...
Here's the 2 stitched images with columns 190 and 300 to the right and rows 768 and 769 below.
and here's a zoom in on a part of the intersection-region:
If you want to level the low-intensity regions you have to adapt my snipped to also select only the low-intensity-regions (here columns ~140-218 etc and calculate the average difference between the pixels in those regions...)
If you want something else you have to give a more detailed explanation.

Sign in to comment.


Dimani4
Dimani4 on 28 Jan 2021
Bjorn,
All I want is to do kind of plane removal of each matrix to get the intensity distribution more homogenical and then to get all the matrices to the same dynamic range to eliminate the differences in the intensities between them as you pointed out in the Figure1 and then to get all the pictures stitched.
Actually I did some kind of very primitive slope removal of every line in each matrix and then got them stitched.
The algorithm is like that:
for sc=1:size(pl_laser_matr,2)
pl_laser_matr{sc}=minus_slope(pl_laser_matr{sc});
end
function matri_compens2=minus_slope(matrix)
matri_compens=matrix;
for i=1:size(matri_compens,2) %minus vertical slope
lineB=(matri_compens(:,i))';
x1=1:size(matri_compens,1);
p1=polyfit(x1,lineB,1);
p1(1);
for j=1:size(matri_compens,1)
new_line1(j,i)=lineB(j)-p1(1)*x1(j);
end
end
matri_compens2=new_line1;
And here is the result of the first matrix:
From the first sight it seems OK however you got some artifacts in the edges, look at the zoom I did in the picture above:
It happens because I apply this algorithm to the straight vertical lines (columns) but my structure is little bit inclined so it creates these artifacts.
Here the whole stitch: (25 frames)
And here is zoom:
You see all these artificial lines (red arrows). Not so good for me.
Thank you for your help.
  3 Comments
Dimani4
Dimani4 on 30 Jan 2021
Edited: Dimani4 on 30 Jan 2021
Thank you Bjorn,
Actually I tried something similar, but maybe I found out more elegant way to do it. What do you think?
I try to fit it to some surface, find out the formula for that surface, find out the points in each (X,Y) and then just subtract them from each point of my Z value.
So what I do:
  1. Find out surface fit to my points:
X=1:size(MyMatrix,2);
Y=1:size(MyMatrix,1);
[x,y]=meshgrid(X,Y);
f2=fit( [x(:), y(:)], MyMatrix(:), 'poly11' ); %linear surface fit
formula(f2)
ans =
p00 + p10*x + p01*y;
coeffs = coeffvalues(f2)
coeffs =
0.1121 0.0000 -0.0001
figure, sd2=plot(f2,[x(:),y(:)],MyMatrix(:));%plotting my matrix with the fit
Now lets plot only the fit.
tyr2=sd2.Parent
mesh(tyr2.Children(2).XData,tyr2.Children(2).YData,tyr2.Children(2).ZData)
Since I know the formula and the coefficients I can make a new Z value corresponding to my surface fit:
Z_new=0.1121+0*x-0.0001*y;
Then I'll subtract MyMatrix-Z_new.
That's the way I do kind of plane compensation.
also I can do quadratic polynomial if I'll do:
f3 = fit( [x(:), y(:)], handles.matrices{1}(:), 'poly22' );
And do the same procedure (i.e. find out new Z_new and substract from MyMatrix).. this how I do quadratic plane compensation... What do you think?
The picture below is quadratic plane after fit (f3).
Bjorn Gustavsson
Bjorn Gustavsson on 30 Jan 2021
If that gives you a correction you're happy with, then all's well that ends well?

Sign in to comment.


Dimani4
Dimani4 on 1 Feb 2021
Edited: Dimani4 on 1 Feb 2021
Hey Bjorn,
Not yet. Now I have a problem of different color scales. Do you know how to bring all the pictures to the same range?
Look at the stitch:
This is the typical surface plane (only first matrix). I guess the other surface planes of other matrices look approx. the same:
Also I saw when I subtract my matrix from the surface plane I got negative numbers, what I did
func_f=str2func(['@(x,y)' fformulaD]);
func_f_fitted_surface_matrix=func_f(x,y);
diff_matr=matrix-func_f_fitted_surface_matrix;
comp_matrix=diff_matr+abs(min(diff_matr(:)));
Thank you.
  9 Comments
Bjorn Gustavsson
Bjorn Gustavsson on 3 Feb 2021
In my comment from "27 Jan 2021 at 16:06" I have a horizontal line-plot in the embedded figure. In that one there are 2 rows plotted, one from just above the stitch, one from just below. In those lines you have low-intensity-regions at (approximately) 150-215, 370-430 and 590-660. Removing the intensity-difference between regions would be my first step. Since your bands have a slight slope you will have to save these indices for each stitching. So in order to run my attempt you would have to make a cell-array with those indices for each stitching. Perhaps a 2-D cell-array would be best, organized to match your image-stitching. Something like this:
iRow = 1;
iCol = 1;
idx_darkBands{iRow,iCol} = [150:215,370:430,590:660];
Then you'd have to add the indices for the dark bands at each stitching in the vertical direction between the first column of images by incremental iRow and then start over with the second column of images. If you do this you'll have to modify my snippet to account for the cell-array being 2D.
Dimani4
Dimani4 on 4 Feb 2021
Hey Bjorn,
Thank you for your suggestion.
I want to take these parts automatically, so I thought to draw profile and just exclude these regions but as it turned out to exclude them its not so easy thing because they are very noisy.
xMatr=1:size(init_matr1,2);
yMatr(1:size(init_matr1,2))=768;
[cx,cy,c]=improfile(init_matr1,xMatr,yMatr);
figure;imagesc(init_matr1);
% colormap(hot(255));
colorbar;
hold on;
plot(xMatr,yMatr,'LineStyle','--','LineWidth',2,'Color','green');
figure;
plot(cx,c);
I took row 768. init_matr1 is the stitched matrix of (768*5X768*5). Here if you want you can download it (https://wetransfer.com/downloads/c0ad07dcadd336b16cd700fd4e6c47c220210204120137/a0983e6fc4cf07d5e59103ef84449f1120210204120205/07b050).
And zoomed region:
What do you think, how can I take these low-intensity regions automatically?
Thank you.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!