MATLAB - How to plot x,y on an image and save? - image

File datafile.txt
code x y
23 22.1 33.11
23 110 22
23 11 200
24 111 321
24 222 111
24 10 22.1
10 88.3 99.3
10 110 32
10 121 143
10 190 200
In the above file, the first column represents the image code which is displayed on the screen, and the x and y columns represent the point where people look on the image. There were three different images displayed to the user. The problem with the code below is that I don't know how to save the image with the plotted x-y on with the same name of file as it opened.
fid = fopen(datafile.txt);
A = textscan(fid,'%f%f%f'); %Read data from the file
code = A{1};
xfix = A{2};
yfix = A{3};
for k=1:length(code)
imagefile=code(k)
I = imread([num2str(imagefile) '.jpg']); %# Load a sample image
imshow(I); %# Display it
[r,c,d] = size(I) %# Get the image size
set(gca,'Units','normalized','Position',[0 0 1 1]); %# Modify axes size
set(gcf,'Units','pixels','Position',[200 200 c r]); %# Modify figure size
hold on;
x = xfix2(k);
y = yfix2(k);
plot(x,y,'+ b');
f = getframe(gcf); %# Capture the current window
imwrite(f.cdata,([num2str(imagefile) '.jpg'])); %# Save the frame data
hold off
end
However, I have a little problem. The "cross plots" which I overlay on the image, were surrounded by gray shadow (like when we photocopy a paper, they will be a gray color on it). How did this happen?

There are numerous ways:
Superimposing line plots on images
Can I use a JPEG file as a background in a MATLAB plot?
How do I add a background image to my GUI or figure window?
And there's always some kind of problem with adjusting the axes afterwards.

Related

Debayering bayer encoded Raw Images

I have an image which I need to write a debayer for, but I can't figure out how the data is packed.
The information I have about the image:
original bpp: 64;
PNG bpp: 8;
columns: 242;
rows: 3944;
data size: 7635584 bytes.
PNG https://drive.google.com/file/d/1fr8Tg3OvhavsgYTwjJnUG3vz-kZcRpi9/view?usp=sharing
SRC data: https://drive.google.com/file/d/1O_3tfeln76faqgewAknYKJKCbDq8UjEz/view?usp=sharing
I was told that it should be BGGR, but it doesn't look like any ordinary Bayer BGGR image to me. Also I got the image with a txt file which contains this text:
Camera resolution: 1280x944
Camera type: LVDS
Could the image be compressed somehow?
I'm completely lost here, I would appreciate any help.
Bayer pattern of the image in 8bpp representation
Looks like there are 4 images, and the pixels are stored in some kind of "packed 12" format.
Please note that "reverse engineering" the format is challenging, and the solution probably has few mistakes.
The 4 images are stored in steps of 4 rows:
aaaaaaaaaaaaa
bbbbbbbbbbbbb
ccccccccccccc
ddddddddddddd
aaaaaaaaaaaaa
bbbbbbbbbbbbb
ccccccccccccc
ddddddddddddd
...
aaa... marks the first image.
bbb... marks the second image.
ccc... marks the third image.
ddd... marks the fourth image.
There are about 168 rows at the top that we have to ignore.
Getting 1280 pixels out of 1936 bytes in each row:
Each row has 16 bytes we have to ignore.
Out of 1936 bytes, only 1920 bytes are relevant (assume we have to remove 8 bytes from each side).
The 1920 bytes represents 1280 pixels.
Every 2 pixels are stored in 3 bytes (every pixel is 12 bits).
The two 12 bits elements in 3 bytes are packed as follows:
8 MSB bits 8 MSB bits 4 LSB and 4 LSB bits
######## ######## #### ####
It's hard to tell how the LSB bits are divided between the two pixels (the LSB it mainly "noise").
After unpacking the pixels, and extracting one image out of the 4, the format looks like GRBG Bayer pattern (by changing the size of the margins we may get BGGR).
MATLAB code sample for extracting one image:
f = fopen('test.img', 'r'); % Open file (as binary file) for reading
T = fread(f, [1936, 168], 'uint8')'; % Read the first 168
I = fread(f, [1936, 944*4], 'uint8')'; % Read 944*4 rows
fclose(f);
% Convert from packed 12 to uint16 (also skip rows in steps of 4, and ignore 8 bytes from each side):
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A = uint16(I(1:4:end, 8+1:3:end-8)); % MSB of even pixels (convert to uint16)
B = uint16(I(1:4:end, 8+2:3:end-8)); % MSB of odd pixels (convert to uint16)
C = uint16(I(1:4:end, 8+3:3:end-8)); % 4 bits are LSB of even pixels and 4 bits are LSB of odd pixels
I1 = A*16 + bitshift(C, -4); % Add the 4 LSB bits to the even pixels (may be a wrong)
I2 = B*16 + bitand(C, 15); % Add the other 4 LSB bits to the even pixels (may be a wrong)
I = zeros(size(I1, 1), size(I1, 2)*2, 'uint16'); % Allocate 1280x944 uint16 elements.
I(:, 1:2:end) = I1; % Copy even pixels
I(:, 2:2:end) = I2; % Copy odd pixels
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
J = demosaic(I*16, 'grbg'); % Apply demosaic (multiply by 16, because MATLAB assume 12 bits are in the upper bits).
figure;imshow(lin2rgb(J));impixelinfo % Show the output image (lin2rgb applies gamma correction).
Result (converted to 8 bit):

How can I create a GTIN14 bar code in ZPL?

Can I print a GTIN-14 barcode using ZPL?
I have searched, but can't find much information on weather or not it is possible to print this type of bar code, including the border around it.
Any help is greatly appreciated.
Thanks!
GTIN-14 is simply an interleaved 2 of 5 barcode with bearer bars and special text formatting. Assuming a 203dpi printer and an approximate x-dimension of 25 mils (.64mm), you can calculate all the dimensions of the barcode and its border box.
25mils is approximately 5 dots at 203dpi.
The barcode height should be 1.25 inches, which is ~250 dots.
The border around the barcode should be the width of the wide bar (3x narrow, or 15 dots).
Each character in the barcode is 45 dots (9 modules * 5 dots).
The start/stop also adds 45 dots (9 modules * 5 dots).
So the total length of the barcode is 15 * 45 dots = 675 dots.
Quite zone is 0.25 inches (50 dots) left and right of the barcode.
So the box around the barcode is 805 dots wide (15 border + 50 quiet + 675 barcode + 50 quiet + 15 border) and 280 dots high (15 border + 250 barcode + 15 border).
Here's how it looks in ZPL:
^XA
^FO100,100^BY5,3
^B2N,250,N,N,N
^FD00012345678905^FS
^FO35,85^GB805,280,15^FS
^FO115,380^AB,44,28^FD0 00 12345 67890 5^FS
^XZ
The top left corner of the barcode is at 100,100. The top left corner of the border box is at 35,85.
The example uses the built-in B font, you may want to change that...
And here it is in labelary.

Sampling a Greyscale image into 8 levels

What I am trying to do:-
Using MATLAB, I am trying to read a Greyscale image (having pixel values bw range 0-255) i.e. an 8bit image into like 3 bit image, hence it is like sampling the range into 8 different levels. For example if the pixel value is 25 then as it comes bw range 0-31, it will be assigned value 0, for bw 32-63 level will be 1 and so on until finally range 224-255 it will be on range 7.
After that I am counting the total no of pixels in different levels.
Code:-
img=imread('Cameraman.bmp');
r=size(img,1);
c=size(img,2);
pixel_count=zeros(9,1);
for i=1:r
for j=1:c
if fix(img(i,j)/31)==8
img(i,j)
end
img(i,j)=fix(img(i,j)/33);
pixel_count(img(i,j)+1)=pixel_count(img(i,j)+1)+1;
end
end
pixel_count
My Problem:-
Even if the range of each pixel is from 0-255, and I am dividing it into 8 levels, I am getting a total of 9 levels.
For debugging it I added the if statement in the code and my output is:--
ans = 248
ans = 250
ans = 249
ans = 249
ans = 235
ans = 249
ans = 249
ans = 235
...and more
pixel_count =
11314
3741
2061
5284
12629
25590
4439
437
41
As you can see for some values like 249,235 and more I am getting the extra 9th level.
What is the problem here. Please help.
Thank You.
You aren't dividing by the right value properly. You need to divide by 32, then take the floor / fix. Between 0-31, if you divide by 32 then take the floor / fix, you get the value 0, between 31-63, you get 1, up until 224-255 which gives you 7.
Also, your for loop is incorrect. You are mistakenly replacing the pixel of the input image with its bin location. I would also change the precision to double. It seems that with my experiments, using fix combined with a uint8 image gives me that random 9th bin index that you're talking about.
Take a look at some sample results from my REPL:
>> fix(240/32) + 1
ans =
8
>> fix(uint8(240)/32) + 1
ans =
9
>> fix(uint8(255)/32) + 1
ans =
9
>> fix(255/32) + 1
ans =
8
Therefore, it's a problem with the image type. For any values that are beyond 240, the value when being divided by 32 as it's uint8 gets rounded so that 240 / 32 = 7.5 but because it's uint8 and it's an integer, it gets rounded to 8, then adding 1 makes it go to 9. Therefore, anything beyond 240 will get rounded to 8 and ultimately giving you 9 when adding by 1.
So, simply change the division to be 32, not 33 or 31 and fix what I said above:
img=imread('Cameraman.bmp');
img = double(img); %// Change
r=size(img,1);
c=size(img,2);
pixel_count=zeros(8,1); %// Change
for i=1:r
for j=1:c
pix = fix(img(i,j)/32); %// Change here
pixel_count(pix+1)=pixel_count(pix+1) + 1; %// Change
end
end
pixel_count
As a minor note, to check to see if you're right, use histc:
pixel_count = histc(fix(double(img(:))/32) + 1, 1:8);
If you got your code right, your code and with what I wrote above should match. Using the cameraman.tif image that's built-in to the Image Processing Toolbox, let's compare the outputs:
>> pixel_count
pixel_count =
13532
2500
2104
8341
15333
22553
817
356
>> pixel_count2 = histc(fix(double(img(:))/32) + 1, 1:8)
pixel_count2 =
13532
2500
2104
8341
15333
22553
817
356
Looks good to me!

Contour Lines Algorithm

This could very well be a duplicate, but I could not seem to find something specific to my problem.
I have a xy grid in a picture box. Each grid cell has a specific mass. I would like to create contour lines on this xy grid based on the mass.
Does anyone have any ideas to a good algorithm to perform this task? I am trying to get this done in VB6 but any algorithm would do.
Edit
Contour Grid
I have a grid. I want to display contour lines based on mass (IE, the cells with more than one point in them will be heavier in mass)
This question's a bit stale, but so's my experience: I did something like this almost 30 years ago.
This produces simple contours on a bitmap:
Calculate the field-strength at each point in the grid (I'm assuming you're trying to plot something like gravitational field contours based on the masses of the points).
Colour the alternate spaces between contour lines (which you haven't got yet) in two alternate colours. e.g. if the contour lines should be 100 units (of field-strength) apart then choose the colour of each pixel based on ToInt(pixel_field_strength / 100) % 2.
Trace the edges of the colour boundaries to produce contours. For example, if your two colours are white and black, then only retain white pixels adjacent to a black pixel.
If you're just interested in the results, use a library as suggested in the comments.
Purely for nostalgia's sake, I found my original BBC BASIC code. It still runs on modelb (a BBC Micro emulator).
10 REM THIS COMES WITH NO WARRANTY!
20
30 REM Gravity field
40
50 MODE 1
60 PROCsetup
70 FOR Y%=300 TO 900 STEP 4
80 FOR X%=200 TO 800 STEP 4
90 R=LOG(FNforce(X%,Y%))
100 GCOL0,((R*10) MOD 2)+1
110 PLOT69,X%,Y%
120 NEXT
130 NEXT
140 PROCcontour
150 VDU19,1,0,0,0,0
160 VDU19,2,0,0,0,0
170 END
180 DEFPROCsetup
190 N%=5
200 DIM X%(N%),Y%(N%),M%(N%)
210 FOR P%=1 TO N%
220 READ X%(P%),Y%(P%),M%(P%)
230 NEXT
240 ENDPROC
250 DATA 625,625,1000000
260 DATA 425,725,1000000
270 DATA 475,425,1000000
280 DATA 375,575,1000000
290 DATA 725,525,1000000
300 DEFFNforce(X,Y)
310 P=0
320 FOR P%=1 TO N%
330 DX=X%(P%)-X:DY=Y%(P%)-Y
340 R=SQR(DX*DX+DY*DY)
350 P=P+M%(P%)/R
360 NEXT
370 =P
380 DEFPROCcontour
390 GCOL0,3
400 FOR Y%=300 TO 900 STEP 4
410 FOR X%=200 TO 800 STEP 4
420 IF POINT(X%,Y%)=1 AND (POINT(X%+4,Y%)=2 OR POINT(X%-4,Y%)=2 OR POINT(X%,Y%+4)=2 OR POINT(X%,Y%-4)=2) THEN PLOT69,X%,Y%
430 NEXT
440 NEXT
450 ENDPROC

How to optimize the layout of rectangles

I have a dynamic number of equally proportioned and sized rectangular objects that I want to optimally display on the screen. I can resize the objects but need to maintain proportion.
I know what the screen dimensions are.
How can I calculate the optimal number of rows and columns that I will need to divide the screen in to and what size I will need to scale the objects to?
Thanks,
Jamie.
Assuming that all rectangles have the same dimensions and orientation and that such should not be changed.
Let's play!
// Proportion of the screen
// w,h width and height of your rectangles
// W,H width and height of the screen
// N number of your rectangles that you would like to fit in
// ratio
r = (w*H) / (h*W)
// This ratio is important since we can define the following relationship
// nbRows and nbColumns are what you are looking for
// nbColumns = nbRows * r (there will be problems of integers)
// we are looking for the minimum values of nbRows and nbColumns such that
// N <= nbRows * nbColumns = (nbRows ^ 2) * r
nbRows = ceil ( sqrt ( N / r ) ) // r is positive...
nbColumns = ceil ( N / nbRows )
I hope I got my maths right, but that cannot be far from what you are looking for ;)
EDIT:
there is not much difference between having a ratio and the width and height...
// If ratio = w/h
r = ratio * (H/W)
// If ratio = h/w
r = H / (W * ratio)
And then you're back using 'r' to find out how much rows and columns use.
Jamie, I interpreted "optimal number of rows and columns" to mean "how many rows and columns will provide the largest rectangles, consistent with the required proportions and screen size". Here's a simple approach for that interpretation.
Each possible choice (number of rows and columns of rectangles) results in a maximum possible size of rectangle for the specified proportions. Looping over the possible choices and computing the resulting size implements a simple linear search over the space of possible solutions. Here's a bit of code that does that, using an example screen of 480 x 640 and rectangles in a 3 x 5 proportion.
def min (a, b)
a < b ? a : b
end
screenh, screenw = 480, 640
recth, rectw = 3.0, 5.0
ratio = recth / rectw
puts ratio
nrect = 14
(1..nrect).each do |nhigh|
nwide = ((nrect + nhigh - 1) / nhigh).truncate
maxh, maxw = (screenh / nhigh).truncate, (screenw / nwide).truncate
relh, relw = (maxw * ratio).truncate, (maxh / ratio).truncate
acth, actw = min(maxh, relh), min(maxw, relw)
area = acth * actw
puts ([nhigh, nwide, maxh, maxw, relh, relw, acth, actw, area].join("\t"))
end
Running that code provides the following trace:
1 14 480 45 27 800 27 45 1215
2 7 240 91 54 400 54 91 4914
3 5 160 128 76 266 76 128 9728
4 4 120 160 96 200 96 160 15360
5 3 96 213 127 160 96 160 15360
6 3 80 213 127 133 80 133 10640
7 2 68 320 192 113 68 113 7684
8 2 60 320 192 100 60 100 6000
9 2 53 320 192 88 53 88 4664
10 2 48 320 192 80 48 80 3840
11 2 43 320 192 71 43 71 3053
12 2 40 320 192 66 40 66 2640
13 2 36 320 192 60 36 60 2160
14 1 34 640 384 56 34 56 1904
From this, it's clear that either a 4x4 or 5x3 layout will produce the largest rectangles. It's also clear that the rectangle size (as a function of row count) is worst (smallest) at the extremes and best (largest) at an intermediate point. Assuming that the number of rectangles is modest, you could simply code the calculation above in your language of choice, but bail out as soon as the resulting area starts to decrease after rising to a maximum.
That's a quick and dirty (but, I hope, fairly obvious) solution. If the number of rectangles became large enough to bother, you could tweak for performance in a variety of ways:
use a more sophisticated search algorithm (partition the space and recursively search the best segment),
if the number of rectangles is growing during the program, keep the previous result and only search nearby solutions,
apply a bit of calculus to get a faster, precise, but less obvious formula.
This is almost exactly like kenneth's question here on SO. He also wrote it up on his blog.
If you scale the proportions in one dimension so that you are packing squares, it becomes the same problem.
One way I like to do that is to use the square root of the area:
Let
r = number of rectangles
w = width of display
h = height of display
Then,
A = (w * h) / r is the area per rectangle
and
L = sqrt(A) is the base length of each rectangle.
If they are not square, then just multiply accordingly to keep the same ratio.
Another way to do a similar thing is to just take the square root of the number of rectangles. That'll give you one dimension of your grid (i.e. the number of columns):
C = sqrt(n) is the number of columns in your grid
and
R = n / C is the number of rows.
Note that one of these will have to ceiling and the other floor otherwise you will truncate numbers and might miss a row.
Your mention of rows and columns suggests that you envisaged arranging the rectangles in a grid, possibly with a few spaces (e.g. some of the bottom row) unfilled. Assuming this is the case:
Suppose you scale the objects such that (an as-yet unknown number) n of them fit across the screen. Then
objectScale=screenWidth/(n*objectWidth)
Now suppose there are N objects, so there will be
nRows = ceil(N/n)
rows of objects (where ceil is the Ceiling function), which will take up
nRows*objectScale*objectHeight
of vertical height. We need to find n, and want to choose the smallest n such that this distance is smaller than screenHeight.
A simple mathematical expression for n is made trickier by the presence of the ceiling function. If the number of columns is going to be fairly small, probably the easiest way to find n is just to loop through increasing n until the inequality is satisfied.
Edit: We can start the loop with the upper bound of
floor(sqrt(N*objectHeight*screenWidth/(screenHeight*objectWidth)))
for n, and work down: the solution is then found in O(sqrt(N)). An O(1) solution is to assume that
nRows = N/n + 1
or to take
n=ceil(sqrt(N*objectHeight*screenWidth/(screenHeight*objectWidth)))
(the solution of Matthieu M.) but these have the disadvantage that the value of n may not be optimal.
Border cases occur when N=0, and when N=1 and the aspect ratio of the objects is such that objectHeight/objectWidth > screenHeight/screenWidth - both of these are easy to deal with.

Resources