imshow/imwrite changes all pixel values to 1 - matlab

I have a Matlab dataset saved with .mat that I'm trying to process in Octave GUI. The data consist of images and I want to save them in a JPG format (or any other image format), but I'm having this strange behavior when trying to displaying or writing the images.
this is how part of the image displays as an array:
91 90 91 88 93
88 91 86 81 88
93 100 90 85 91
93 100 94 93 96
87 87 87 87 89
But when I write the image
imwrite(img, 'D:\image_test_1.jpg')
and read it again
img_read=imread('D:\image_test_1.jpg')
I end up with this:
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
I tried searching for the cause, but couldn't find a definitive answer or clarification to this problem. Even when I'm using imshow to display the image I end up with a blank image.
What happened to all the pixel values?

Configuring as uint8 Image
To indicate that this image is using an 8-bit scale/format we can caste the array as an uint8() (unsigned 8-bit integer). This format will assume the intensity values range from 0 to 255 (typical JPG format). I think the reason for the array showing up as 1s is that Octave is trying to parse the array as a double ranging from 0 to 1. Therefore the results of the array are reaching the ceiling of 1 since all the intensity values of the Image/img array are out of range (maxed out). Alternatively we can convert the array to double using the im2double() function or diving the original array by 255.
Image = [91 90 91 88 93;
88 91 86 81 88;
93 100 90 85 91;
93 100 94 93 96;
87 87 87 87 89];
Image = uint8(Image);
imwrite(Image, 'D:\image_test_1.jpg')
imshow(imread('D:\image_test_1.jpg'),'InitialMagnification','fit');
Ran using MATLAB R2019b

Related

Black line in GLCM result

It is the result of GLCM matrix. What is the meaning of black horizontal and vertical lines in GLCM image? Are they a problem?
N = numel(unique(img)); % img is uint8
glcm = graycomatrix(img, 'NumLevels', N);
imshow(glcm)
I suspect this is the problem: For the function graycomatrix, You have supplied a 'NumLevels' argument which is larger than the number of unique graylevels in your image. For instance, a 256-level (8-bit) image will have only 256 graylevels. Asking for 1000 levels in the output means 744 levels will have no data! i.e. Yes, this is a problem. You can check how many graylevels your image has using numel(unique(I)).
p.s. In the future, please attach the code you used to generate the problem.
graycomatrix calculates the GLCM from a scaled version of the image. Due to round-off errors in the scaling process the number of different intensity levels in the scaled image may be less than the number of different intensity levels in the original image .
Consider the following sample image:
img = uint8([ 48 161 209 64 133 240 166 227;
184 54 181 33 107 252 242 255
217 191 125 112 204 252 135 201
163 222 66 125 229 140 38 97
252 214 201 191 10 102 242 74
191 74 77 8 163 51 189 186]);
From the documentation (emphasis mine):
[glcms,SI] = graycomatrix(___) returns the scaled image, SI, used to calculate the gray-level co-occurrence matrix. The values in SI are between 1 and NumLevels.
If you set NumLevels to the number of different intensity levels (which in this example is 39)
N = numel(unique(img))
[glcm_scaled, img_scaled] = graycomatrix(img, 'NumLevels', N);
the returned GLCM has 39*39 elements. The issue is that the scaled image has only 28 different intensity levels:
>> img_scaled
img_scaled =
8 25 32 10 21 37 26 35
29 9 28 6 17 39 38 39
34 30 20 18 32 39 21 31
25 34 11 20 36 22 6 15
39 33 31 30 2 16 38 12
30 12 12 2 25 8 29 29
>> numel(unique(img_scaled))
ans =
28
As a consequence, the GLCM will have 11 rows and 11 columns in which all the entries are zero (black lines).
If you do not wish this to happen, you can map the intensity levels through a lookup table:
levels = unique(img);
N = numel(levels);
lut = zeros(256, 1);
for i=1:N;
index = uint16(levels(i)) + 1;
lut(index) = i;
end
img_lut = lut(uint16(img) + 1);
[glcm_mapped, img_mapped] = graycomatrix(img_lut, 'NumLevels', N, 'GrayLimits', []);
By doing so, img_mapped is exactly the same as img_lut and there is no black lines in the GLCM. Notice that by specifying empty brackets for the GrayLimits parameter, graycomatrix uses the minimum and maximum grayscale values in the input image as limits.
I was seeing the same behaviour under my own GLCM implementation.
The issue was that I was implementing the histogram equalization given a number of gray levels.
I compute the discretization of the image before dividing first and then enter to review if any row or column is given inly zeros values.

Importing CSV into Matlab

Chemical composition of a certain material
Hi,
I am trying to import the below mentioned data in CSV format in matlab, which is [1000x10] in dimensions.
HCL;H2SO4;CH4; SULPHUR;CHLORINE;S2O3;SO2;NH3;CO2;O2
144 2 3 141 140 6 7 137 136 10 11 133
13 131 130 16 17 127 126 20 21 123 122 24
25 119 118 28 29 115 114 32 33 111 110 36
108 38 39 105 104 42 43 101 100 46 47 97
96 50 51 93 92 54 55 89 88 58 59 85
61 83 82 64 65 79 78 68 69 75 74 72
73 71 70 76 77 67 66 80 81 63 62 84
60 86 87 57 56 90 91 53 52 94 95 49
48 98 99 45 44 102 103 41 40 106 107 37
109 35 34 112 113 31 30 116 117 27 26 120
121 23 22 124 125 19 18 128 129 15 14 132
12 134 135 9 8 138 139 5 4 142 143 1
I am able to import this data through my code
fid = fopen(uigetfile('.csv'),'rt');
FileName = fopen(fid);
headers = fgets(fid); %get first line
headers = textscan(headers,'%s','delimiter',';'); %read first line
format = repmat('%f',1,size(headers{1,1},1)); %count columns n makeformat string
data = textscan(fid,format,'delimiter',';'); %read rest of the file
data = [data{:}];
I am getting data in matrix form in variable data [1000x10] and name of all the components like HCL, H2SO4 in a cell array named headers{1x1}.
Now I have two questions like the built in import feature in matlab you have flexibility to import data as separate column vectors, numeric matrix,cell array and table format. Is it possible to do as such through code, like i get column vectors with their name HCL with [1000x1] and H2sO4 with [1000x1] in my workspace after import and so on all the column vectors with their names with [1000x1]dimensions.
if yes then help me please...?
If above mentioned is not possible then i can do alternatively that now I have names of column vectors in headers cell array, how I can extract those name and use those names as column vector names through code and I can assign data from data matrix [1000x10] to each column vector with their corresponding names.
like if i say
x = headers {1*1}{1*1}; i will get x = "HCL"
x = genvarname(x); I will get x= x0x22HCL0x2 BUT
I want that x get replaced with HCL.and then I assign
HCL = data(:,1) and same like this other variables H2SO4,SULPHUR, CHLORINE.
You can say i try to implement the import feature of column vector through my code.
Kindly help me to solve this issue. thanks
Have you tried the built-in readtable function?
You can access each column of the table by using the named column header.
If you'd like, you can use the two data types to create a table in MatLab. I'm not terribly familiar with its use, but it seems to be well documented. I'm sure someone else can expand upon this.
Edit:
After re-reading your question, I think this is closer to what you are after.
n=10;
what='HCL';%change this to any of the strings you interested in
numstr = repmat('%f',1,n);
hdrstr = repmat('%s',1,n);
headers = textscan(headers,hdrstr,'delimiter',';');
headers = headers(1,:)
data = cell2mat(textscan(fid,numstr,'delimiter',';'));
datout = data(:,strcmp(headers,what));%datout will be 1000x1 HCL data
Depending on what you want to do, you can loop through these appropriately
I know this is not what you asked for, but I would convert to a struct:
x=cell2struct(num2cell(data),headers,2)
reason is simple, selecting for example the third row with individual variables is not possible. With a struct simply use x(3)
If at some point you need the vectors you originally asked for and you can't use the strcut, use [x.HCL]

read/load parts of the irregular file by Matlab

I would like to partly load a PTX file by matlab (please see the following example)
I need to read and write the first two row (2 numbers) into 2 variables say a and b. And read and write the data from 5th row to the end into a matrix
Thanks for your help
114
221
1 0 0
1 0 0 0
-5.566405 -7.161944 -1.144557 0.197208 24 29 35
-5.560656 -7.154540 -1.137673 0.222400 29 32 39
-5.559846 -7.153491 -1.131895 0.254002 37 40 49
-5.560894 -7.154833 -1.126452 0.305013 51 54 63
-5.560084 -7.153783 -1.120633 0.290013 72 76 88
-5.561128 -7.155119 -1.115189 0.243214 105 113 134
-5.563203 -7.157782 -1.109926 0.227604 130 143 177
-5.569191 -7.165479 -1.105504 0.201602 121 140 173
-7.833616 -10.078705 -1.546952 0.130007 94 112 134
Look at the tdfread function in order to get the data into Matlab. It should be something like datafile = tdfread(filename, '\t'). Once you have that, index into the variable returned from that function like
a = datafile(1, 1);
b = datafile(2, 1);
data = datafile(5:end, :);

Matlab .txt file read using space delimiter

I want to read a text file into a matrix using space delimiter.My text file contains information like this:
AJ_Lamas/AJ_Lamas_0001.jpg 58 68 134 134 -2 10 31 43 53 45
Aaron_Eckhart/Aaron_Eckhart_0001.jpg 63 72 126 126 0 10 34 35 53
Aaron_Guiel/Aaron_Guiel_0001.jpg 54 67 144 144 -1 10 34 44 58
Aaron_Patterson/Aaron_Patterson_0001.jpg 47 62 148 148 1 10 44 65 63
Aaron_Peirsol/Aaron_Peirsol_0001.jpg 64 72 127 127 0 10 33 43
I tried :
m=dlmread('D:\MatlabCode\lfw_ffd_ann.txt', ' ')
but it shows some errors:
Error using dlmread (line 139)
Mismatch between file and format string.
Trouble reading number from file (row 1u, field 1u) ==> image_name
face_bbox_x face_bbox_y face_bbox_width face_bbox_height headpose
num_facial_features left_eye_left_x left_eye_left_y left_eye_right_x
left_eye_right_y mouth_left_x mouth_left_y mouth_right
You can't really read it itno a matrix, but into a cell and can achieve it with textscan(). Supposing you want to read the actuall strings (which I assume because of the file names), it would go something like this:
fid=fopen('D:\MatlabCode\lfw_ffd_ann.txt');
C=textscan(fid,'%s','delimiter',' ');
fclose(fid);
hope that helps

Selecting elements of a vector based on two vectors of starting and ending positions matlab

I would appreciate your help with the following problem in matlab:
I have a vector and I would like to select parts of it based on the following two vector of start and end indices of parts:
aa = [1 22 41 64 83 105 127 147 170 190 212 233]
bb = [21 40 63 82 104 126 146 169 189 211 232 252]
Basically I would like to perform some function on V(1:21), V(22:40),... V(233:252).
I have tried V(aa:bb) or V(aa(t):bb(t)) where t = 1:12 but I get only V(1:21), probably because V(22:40) has 19 elements compared to V(1:21) which has 22 elements.
Is there a fast way of programming this?
Put your selection in a cell array, and apply your function to each cell:
aa = [1 22 41 64 83 105 127 147 170 190 212 233]
bb = [21 40 63 82 104 126 146 169 189 211 232 252]
V = rand(252,1); % some sample data
selV = arrayfun(#(t) V(aa(t):bb(t)), 1:12,'uniformoutput',false);
result = cellfun(#yourfunction,selV)
% or
result = cellfun(#(selVi) yourfunction(selVi), selV);
If the function you want to apply has scalar output to every vector input, this should give you an 1x12 array. If the function gives vector output, you'll have to include the uniformoutput parameter:
result = cellfun(#(selVi) yourfunction(selVi), selV,'uniformoutput',false);
which gives you a 1x12 cell array.
If you want to run this in a highly condensed form, you can write (in two lines, for clarity)
aa = [1 22 41 64 83 105 127 147 170 190 212 233]
bb = [21 40 63 82 104 126 146 169 189 211 232 252]
V = rand(252,1); % some sample data borrowed from #Gunther
%# create an anonymous function that accepts start/end of range as input
myFunctionHandle = #(low,high)someFunction(V(low:high));
%# calculate result
%# if "someFunction" returns a scalar, you can drop the 'Uni',false part
%# from arrayfun
result = arrayfun(myFunctionHandle(low,high),aa,bb,'uni',false)
Note that this may run more slowly than an explicit loop at the moment, but arrayfun is likely to be multithreaded in a future release.