Image Compression Algorithm Error
3 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
I'm trying to take a compression factor N and compress all color intensity values in an image according to that factor. But in the code that I wrote there is an error which makes the image wrong and I couldn't find it. Here's my code:
function [comp_img, time] = compress_image(varargin)
clc
% Replace 'outputs' and 'inputs' and the function name appropriately
%% Define different use cases of the function using varargin and nargin
path = "images/spiral.jpg";
N = 8;
switch nargin
case 1
path = varargin{1};
case 2
if ~isempty(varargin{1})
path = varargin{1};
end
N = varargin{2};
end
img = imread(path);
comp_img = zeros(size(img), "uint8");
tic
%% Define the subrange limits and mapped values
lower_limits = 0:(256/N):(256-(256/N));
upper_limits = lower_limits + (256/N) - 1;
new_values = floor((0:N-1) * 256 / N + 256 / (2 * N));
for channel = 1:3
%% Map the pixel values of the original image to their new values
for i = 1:N
mask = (img(:,:,channel) >= lower_limits(i)) & (img(:,:,channel) <= upper_limits(i));
comp_img(mask, channel) = new_values(i);
end
end
% Record the elapsed time for this step
time = toc;
%% Define a file name and save the output image as a mat file
% File name format should be '{image name}_comp_{compression factor}, '
[~, name, ~] = fileparts(path);
save(name + "_comp_" + N, '-mat');
figure;
subplot(1, 2, 1), imshow(img), title('Original Image');
subplot(1, 2, 2), imshow(comp_img), title(['Compressed Image (N=' num2str(N) ')']);
% Display the elapsed time
fprintf('Elapsed Time: %.4f seconds\n', time)
end
The output is a matrix with the size of 262144x512x3, where th
e original size of the image is 512x512x3. And this is the result:
0 comentarios
Respuestas (2)
Yash
el 13 de Dic. de 2023
Editada: Yash
el 20 de Dic. de 2023
Hi Yigit,
I understand that you want to compress all color intensity values in an image according to compression factor "N". Upon investigating the code, the following line seems to be behind the error:
comp_img(mask, channel) = new_values(i);
As you want to populate "comp_img" with "new_values(i)" where the "mask" value is 1 for the given "channel" value, the correct way to do this is to extract the rows and columns where the "mask" value is 1 and update those values in "comp_img". Here is the code snippet for your reference:
for channel = 1:3
%% Map the pixel values of the original image to their new values
for i = 1:N
mask = (img(:,:,channel) >= lower_limits(i)) & (img(:,:,channel) <= upper_limits(i));
[row, col] = find(mask);
for j = 1:size(row)
comp_img(row(j), col(j), channel) = new_values(i);
end
end
end
The updated code generates a matrix of size 512x512x3, where the original size of the image is 512x512x3.
Refer here for documentation of "find" function for more information: https://www.mathworks.com/help/matlab/ref/find.html
I hope this helps!
0 comentarios
DGM
el 13 de Dic. de 2023
Editada: DGM
el 13 de Dic. de 2023
Your problem is a matter of trying to address the pages of an ND array using a mix of 2D logical addressing and subscript addressing. I included a crude example of one way to avoid the problem (I stripped out the core functionality).
I also include an example which does the same thing, but is written in a manner which works with any image class, any color depth, and doesn't require loops.
% a test image (uint8, RGB)
%A = im2uint8(repmat(permute(parula(500),[3 1 2]),[80 1 1]));
A = imread('a.png');
N = 4;
B = testme(A,N); % your example (crudely fixed)
C = testme2(A,N); % a simplified example that does the same thing
outpict = [A;B;C];
imshow(outpict,'border','tight')
While your code relies on the image being both RGB and uint8-class, the second example does not. Both functions always return uint8-class images
A16 = im2uint16(A); % RGB, uint16
N = 4;
B = testme(A16,N); % result is almost completely truncated
C = testme2(A16,N); % result is same as before
outpict = [A;B;C];
imshow(outpict,'border','tight')
Not only is it more generalized, it's succinct, and it's faster.
tic; B = testme(A,N); toc
tic; C = testme2(A,N); toc
0 comentarios
Ver también
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!