Splitting a color image into sub-images only displays the yellow color

10 ビュー (過去 30 日間)
Bas Carpentero
Bas Carpentero 2022 年 12 月 6 日
コメント済み: Bas Carpentero 2022 年 12 月 7 日
I'm trying to create my own datasets for testing stitching algorithms by splitting images into sub-images. The script I wrote succesfully extracts the relevant rgb values from the correct pixels that make up a certain sub-image, but when I try to display the image I get only a yellow color. (I'm aware this code doesn't take edge cases into account)
Am I switching up the rgb values somewhere or am I using the wrong function to display the subimage? I'm out of ideas.
This is the original picture I used:
This is the first 600 x 400 pixel sub-image.
I = imread("AnyImage");
Error using imread>get_full_filename
File "/Users/bascarpentero/Desktop/Thesis/Image stitching/highres" does not exist.

Error in imread (line 372)
fullname = get_full_filename(filename);
imshow(I)
I(1,2,:)
[names, images] = split(I, 10, 10);
IS = squeeze(images(1,2,:,:,:));
size(IS)
IS(1,2,:)
image(IS)
% SPLIT_IMAGE splits an image into a nrows by ncolumns grid of sub-images.
function [names, images] = split(image, nrows, ncolumns, ~)
[rows, columns, ~] = size(image);
subimage_height = round(rows/nrows);
subimage_width = round(columns/ncolumns);
subimage_names = strings(nrows, ncolumns);
subimages = zeros(nrows, ncolumns, subimage_height, subimage_width, 3);
for r = 1:nrows
for c = 1:ncolumns
formatspec = "subimage_%s";
A = [int2str(r) int2str(c)];
subimage_names(r, c) = sprintf(formatspec, A);
subimages(r, c, :, :, :) = image((r-1)*subimage_height+1:r*subimage_height, ...
(c-1)*subimage_width+1:c*subimage_width, :);
end
end
names = subimage_names;
images = subimages;
end

採用された回答

DGM
DGM 2022 年 12 月 7 日
編集済み: DGM 2022 年 12 月 7 日
This is an issue of data class and scale. You're (implicitly) preallocating your output to a floating point class. Your input data is uint8. You end up populating the output array with data that's scaled improperly for its class. It's not (necessarily) destructive to handle images that are improperly-scaled floating point, but tools like imshow() and imwrite() won't know what to do with them.
Floating point images are expected to be unit scale ([0 1]). You're feeding imshow() an image that's scaled to [0 255]. As a result, almost everything is whiter than white.
The simple way to fix this:
subimages = zeros(nrows, ncolumns, subimage_height, subimage_width, 3, class(image));
Also, naming things "image" isn't good practice, since it's not descriptive, and it shadows the function image(). That said, it's not going to hurt anything here.
For what it's worth, I'd do the splitting like this:
inpict = imread('peppers.png'); % a 384x512x3 image
% use MIMT imdetile()
tiling = [10 10]; % [y x]
outpict = imdetile(inpict,tiling,'direction','col'); % detile to 38x51x3x100
% if you don't like the fact that the tile indexing is 1-dimensional
% you can shove the 4D stack into a cell array and reshape it
outpict = squeeze(num2cell(outpict,[1 2 3]));
outpict = reshape(outpict,tiling) % a 10x10 cell of 38x51x3 images
% ... save the files or something
At this point, you can save the tiles in a loop or whatever. Unless you want to operate on the entire array at once, it's often better to use cell arrays for this sort of thing, as it allows for some better memory management under the hood.
Unlike most mat2cell()-based approaches that get recommended, MIMT imdetile() will detile any image regardless of whether it's integer-divisible by the tiling.
  2 件のコメント
Bas Carpentero
Bas Carpentero 2022 年 12 月 7 日
This solved my main problem for me, thank you! I'm planning to implement overlapping splits and adding noise so I don't think imdetile is the way to go for me, but I'll take a look at it for sure.
DGM
DGM 2022 年 12 月 7 日
編集済み: DGM 2022 年 12 月 7 日
Yeah, if you're going to do overlapping tiles, imdetile() won't help. The tool that makes imdetile() work is maketileable(), but that won't really work either.
Bear in mind that there is currently a minor bugfix in maketileable() that hasn't been published yet. It shouldn't be of consequence here, but if you find the internals to be confusing, that might be why.
You already have your thoughts invested in the code you're writing, so I don't know how much headaches you'll save by trying to adapt my ideas.

サインインしてコメントする。

その他の回答 (1 件)

Constantino Carlos Reyes-Aldasoro
Constantino Carlos Reyes-Aldasoro 2022 年 12 月 6 日
From the images it seems that your channel (the yellow one) is saturated. Have you tried to display the three RGB channels is separate subplots? I.e.
subplot(221); imshow(I)
subplot(222); imshow(I(:,:,1))
subplot(223); imshow(I(:,:,2))
subplot(224); imshow(I(:,:,3))
That is assuming of course that I has dimensions like (r,c,3) for the number of rows, columns and 3 for RGB. Another thing you can do to find out more of the nature of the yellow image is to add a colorbar, that will show you the range of values you are working with.
Hope this helps
  5 件のコメント
Constantino Carlos Reyes-Aldasoro
Constantino Carlos Reyes-Aldasoro 2022 年 12 月 7 日
I think that we are going back to the main question, that is what is what you really need? Just display and visualise the three RGB channels? Or you need something else. If it is just about things "looking" right, then there are many ways to solve this, for instance
Let's create an image with only a saturated red channel:
a=zeros(64,64,3);
a(:,:,1) = 50+300*rand(64,64);
imshow(a)
As mentioned by DGM, you also have to be aware of the data types you are working with, these were doubles, so you can "see" this better if you divide by the maximum and use imagesc instead of imshow:
imagesc(a/max(a(:)))
or even converting the doubles to uints would help if you want to keep imshow
imshow(uint8(a))
What data types are you working with? use "whos" in the command line and that will help. Also look for the maximum values of your data:
max_a = max(a(:))
max_a = 349.9974
If you are using uint8, then the maximum value before saturation will be 255 so you can normalise your data to have a maximum of 255
a2 = uint8(255*a/max_a);
imshow(a2)
And now the problem of saturation is solved.
Hope that this has given you enough information to solve your problem.
Bas Carpentero
Bas Carpentero 2022 年 12 月 7 日
My main problem was not being able to correctly combine the color channels into making a sub-image that looked like a snippet from the original image. Some other user solved my problem for me in the meantime, but thanks for giving me some insight into the workings of the rgb channels!

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeImage Processing Toolbox についてさらに検索

製品


リリース

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by