How to split an image into several curved shape small images?

2 次查看(过去 30 天)
I have an image and I want to divide it into small curved shape image without using manual cropping. For example the attached input will be splited into curved shape small region which are indicated by the line.
Thanks for the help in advance.
  1 个评论
Bjorn Gustavsson
Bjorn Gustavsson 2021-8-11
My code snippet were an example for how you would calculate/extract one such curved segment - provided that the boundary had a shape proportional to cos(x*2*pi/n_hor_pix) and of a known width. For you to use that snippet, you would have to come up with a way to generate the segment boundaries in a neat fashion - I expect that you don't want the lines you have drawn (I guess) in red above and that those are more representative of what you want, If you can model those with some kind of simple sin/bell-type curve you could modify the generation of the y-coordinate in my example reasonably easy. If I've interpreted your question wrong then you might have to explain more precisely what you want.

请先登录,再进行评论。

采纳的回答

Image Analyst
Image Analyst 2021-8-11
Try this:
% Demo to find layers in a cross sectional image.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
grayImage = imread('C2_down5um_246.jpg');
% Get the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(grayImage)
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
% Extract the red channel (so the magenta lines will be white).
grayImage = grayImage(:, :, 1);
end
%--------------------------------------------------------------------------------------------------------
% Display the image.
subplot(2, 2, 1);
imshow(grayImage, []);
axis('on', 'image');
title('Original Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
hFig = gcf;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
% Binarize
lowThreshold = 35;
highThreshold = 255;
% [lowThreshold, highThreshold] = threshold(lowThreshold, highThreshold, grayImage);
mask = grayImage > lowThreshold;
% Take largest blob
mask = bwareafilt(mask , 1);
% Display the image.
subplot(2, 2, 2);
imshow(mask, []);
axis('on', 'image');
title('Mask', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
% Scan to get the top row.
[rows, columns] = size(mask);
% Find top curve first.
topRows = nan(1, columns);
for col = 1 : columns
t = find(mask(:, col), 1, 'first');
if ~isempty(t)
topRows(col) = t;
end
end
hold on;
plot(topRows, 'r-', 'LineWidth', 3)
% Display the image.
subplot(2, 2, 3);
imshow(grayImage, []);
axis('on', 'image');
title('Original Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
drawnow;
hold on;
% Make a bunch of them, each lower than the previous.
deltay = round(rows/8)
allCurves = nan(7, columns);
nonObjectIndexes = isnan(topRows);
for k = 1 : 7
% Get this curve.
thisRow = topRows + (k-1) * deltay;
% Clip it to the bottom of the image.
thisRow = min(thisRow, rows);
% Make columns where there was no object NaN again - they were 365.
thisRow(nonObjectIndexes) = nan;
allCurves(k, :) = thisRow;
plot(thisRow, 'r-', 'LineWidth', 3)
end
Not sure what you want to do after that though. And is it really necessary to extend the curves all the way to the left and right edge of the image when there's nothing there? If so, we could fit the curve to a quadratic with polyfit() and extend it that way.
  17 个评论
Image Analyst
Image Analyst 2021-8-13
I think you could have done it if you had actually tried. But anyway, the solution is attached.

请先登录,再进行评论。

更多回答(2 个)

Bjorn Gustavsson
Bjorn Gustavsson 2021-8-11
编辑:Bjorn Gustavsson 2021-8-11
You should be able to do that with interp2, you just have to select the coordinates of your curved regions to use for interpolating points. Something like this:
Im = peaks(234);
y = 1:23;
x = 1:234;
[x,y] = meshgrid(x,y);
y = y + 130 -30*cos(x*2*pi/234); % This is just an illustrating example for your curve
subplot(2,2,1)
imagesc(Im)
hold on
plot(x(1,:),y(1,:),'k.')
plot(x(end,:),y(end,:),'k.')
peaksCurved = interp2(1:234,1:234,Im,x,y);
subplot(2,2,2)
imagesc(peaksCurved)
caxis([-6.5493, 8.106])
subplot(2,2,3)
pcolor(x,y,peaksCurved),caxis([-6.5493, 8.106]),shading flat
axis ij
axis([1 234 1 234])
HTH
  6 个评论
Dynamic
Dynamic 2021-8-11
@Bjorn Gustavsson & @Image Analyst I am trying to divide the image (C2_down5um_246.jpg) into several parts like 1,2,3,4 and so on which indicated by test.jpg. Now, please help me to divide the image.
Thanks a lot
Bjorn Gustavsson
Bjorn Gustavsson 2021-8-12
"indicated by test.jpg" is not specific enough for us to understand by what criteria you want your region boundaries to be determined.
Image Analyst below guesses that it is some gray-level intesity-boundary for the topmost region and then shifts it downward. I guessed that you could use some kind of functional form for the boundaries and get the intensities in the curved regions by interpolation.
You will have to understand that in order to get a solution that gives you precisely what you want you will have to precisely specify what it is you want. Your hand-scribbled boundaries can be used to generate boundaries but that is: a a hassle, and b seems rather imprecise and arbitrary.
Repeating your reference to the image with your scribbly lines will not give us any new and more precise information.

请先登录,再进行评论。


Image Analyst
Image Analyst 2021-8-11
Please attach your original image.
What I'd do is to try to get the upper surface/curve first since that is the brightest. You might be able to just threshold and then scan across finding the first pixel above the threshold. Then for the lower curves, just subtract some number from the top one. Something like
mask = grayImage > someValue;
mask = bwareafilt(mask, 1); % Take largest to try to get rid of noise.
[rows, columns] = size(mask);
% Find top curve first.
topRows = nan(1, columns);
for col = 1 : columns
t = find(mask(:, col), 1, 'first')
if ~isempty(t)
topRows(col) = col;
end
end
hold on;
% Make a bunch of them, each lower than the previous.
deltay = round(rows/8)
allCurves = zeros(7, columns);
for k = 1 : 7
allCurves(k, :) = topRows + (k-1) * deltay;
plot(allCurves(k, :), 'r-', 'LineWidth', 3)
end
% Clip to bottom of image
allCurves = min(allCurves, rows);
  2 个评论
Dynamic
Dynamic 2021-8-11
My goal is split the image into small images which are in curved shape. So, my expected output for first shape indicated by 1 and second shaped represented by 2 and so on. Again I want to reconstruct my whole image. Please find the attached and expected output.
Thanks a lot for your help
Dynamic
Dynamic 2021-8-13
@Image Analyst, Thanks for your support. Yes, I can add noise to whole image, however, I wanted to add different varience of noise for each band. Thanks for your code.
However, still, I have a question to sort out. If I want to 50% overlap band, then how to modify this code? Please, can you modified the code for that?
Thanks a lot

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Images 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by