How to create 2-D arrays in systemverilog and call the elements in this array later? - fpga

I am writing a little game on FPGA in System Verilog and I want to show some small pictures through VGA display. My picture size is 35px X 20px. I converted the picture into three separate arrays (R, G and B values)by using Matlab. I do not know how I can create similar arrays in System Verilog and then call elements in them later. Below is my current code where I have made white dots and red dots. I want to replace these dots with the pictures I mentioned above. Thanks!
begin:RGB_Display
if (missile_On == 1'b1)
begin
Red = 8'h00;
Green = 8'hff;
Blue = 8'h3f;
end
else if (ourMissileOn == 1'b1)
begin
Red = 8'hff;
Green = 8'hff;
Blue = 8'h00;
end
else if ((ball_on == 1'b1))
begin
Red = 8'hff;
Green = 8'hff;
Blue = 8'hff;
end
else if ((enemyAppear == 1'b1))
begin
Red = 8'hff;
Green = 8'h00;
Blue = 8'h2f;
end
else
begin
Red = 8'h3f;
Green = 8'h00;
Blue = 8'h3f; //- DrawX[9:3];
end
end

You can store color information in 24 bit register as
24'hRRGGBB, (RR - Red, GG - Green, BB - Blue) - one pixel
35px x 20px = 700px, 700 * 3 bytes = 2100 bytes
First 35 * 3 = 105 bytes of memory is a first row of image.
Second 35 * 3 = 105 bytes of memory is a second row of image.
....
You can use FPGA Block RAM.

Related

love2d connecting line segment objects to make a pencil tool that draws lines

I'm trying to create a game that is similar to line rider. I've kind of programmed a pencil right now except that the lines are scattered objects.
I want to be able to connect those red dots to make a smooth line so that the ball can roll across it.
It should more look like this
This is my code
function love.load()
printx = 0 --position to be drawn on when the mouse is pressed
printy = 0 --position to be drawn on when the mouse is pressed
love.physics.setMeter(64) --the height of a meter our worlds will be 64px
world = love.physics.newWorld(0, 9.81*64, true) --The world the everything exists in. Horizontal gravity=0. Bertical gravity=9.81. True says that the world is allowed to sleep.
objects = {} -- table to hold all our physical objects
--let's create the ground
objects.lines = {}
objects.ground = {}
objects.ground.body = love.physics.newBody(world, 650/2, 650-50/2)
objects.ground.shape = love.physics.newRectangleShape(650, 50) --make a rectangle with a width of 650 and a height of 50
objects.ground.fixture = love.physics.newFixture(objects.ground.body, objects.ground.shape); --attach shape to body
--let's create a ball
objects.ball = {}
objects.ball.body = love.physics.newBody(world, 650/2, 600, "dynamic") --Determines where the object will start. In the center of the world and dynamic(moves around)
objects.ball.shape = love.physics.newCircleShape(20) --the ball's shape has a radius of 20
objects.ball.fixture = love.physics.newFixture(objects.ball.body, objects.ball.shape, 1) -- Attach fixture to body and give it a density of 1.
--initial graphics setup
love.graphics.setBackgroundColor(0.41, 0.53, 0.97) --set the background color to a nice blue
love.window.setMode(650, 650) --set the window dimensions to 650 by 650
end
function love.update(dt)
world:update(dt) --this puts the world into motion
if love.mouse.isDown(1) then
local printx = love.mouse.getX()
local printy = love.mouse.getY()
line = {}
line.body = love.physics.newBody(world, printx, printy, "static")
line.shape = love.physics.newRectangleShape(0, 0, 5, 5)
line.fixture = love.physics.newFixture(line.body, line.shape, 5) -- A higher density gives it more mass.
table.insert(objects.lines, line)
love.graphics.setColor(50,50,50)
love.graphics.polygon("fill", line.body:getWorldPoints(line.shape:getPoints()))
end
end
function love.draw()
love.graphics.setColor(0.28, 0.63, 0.05) -- set the drawing color to green for the ground
love.graphics.polygon("fill", objects.ground.body:getWorldPoints(objects.ground.shape:getPoints())) -- draw a "filled in" polygon using the ground's coordinates
love.graphics.setColor(0.76, 0.18, 0.05) --set the drawing color to red for the ball
love.graphics.circle("fill", objects.ball.body:getX(), objects.ball.body:getY(), objects.ball.shape:getRadius())
for _, block in pairs(objects.lines) do
love.graphics.polygon("fill", block.body:getWorldPoints(block.shape:getPoints()))
end
end
Within love.update
if not love.mouse.isDown(1) then
oldx = nil
oldy = nil
end
--draw lines when the mouse is down
if love.mouse.isDown(1) then
local printx = love.mouse.getX() + Camera.x --x coordinate of the mouse
local printy = love.mouse.getY() + Camera.y --y coordinate of the mouse
if oldx ~= nil then
line = {}
line.x1 = oldx
line.x2 = printx
line.y1 = oldy
line.y2 = printy
line.body = love.physics.newBody(world, 0, 0, "static")
line.shape = love.physics.newEdgeShape(printx, printy, oldx, oldy)
line.fixture = love.physics.newFixture(line.body, line.shape, 5)
table.insert(objects.lines, line)
end
oldx = printx
oldy = printy
end
Within love.draw()
for _, line in pairs(objects.lines) do
love.graphics.line( line.x1 - Camera.x, line.y1 - Camera.y, line.x2 - Camera.x, line.y2 - Camera.y) --:getWorldPoints(block.shape:getPoints()))
end

Matlab image - how to count number of white pixels

The matlab code below splits up an image into a number of smaller images. It then counts the number of black pixels in the image and displays it as a percentage of the total number of pixels in the picture. example of image
My question is - instead of counting the black pixels and displaying the percentage, how can I count the white pixels? (essentially the opposite!)
Thanks
% Divide an image up into blocks (non-overlapping tiles).
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
workspace; % Make sure the workspace panel is showing.
fontSize = 20;
% Read the image from disk.
rgbImage = imread('edge-diff.jpg');
% Display image full screen.
imshow(rgbImage);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
drawnow;
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows columns numberOfColorBands] = size(rgbImage)
%==========================================================================
% The first way to divide an image up into blocks is by using mat2cell().
blockSizeR = 400; % Rows in block.
blockSizeC = 400; % Columns in block.
% Figure out the size of each block in rows.
% Most will be blockSizeR but there may be a remainder amount of less than that.
wholeBlockRows = floor(rows / blockSizeR);
blockVectorR = [blockSizeR * ones(1, wholeBlockRows), rem(rows, blockSizeR)];
% Figure out the size of each block in columns.
wholeBlockCols = floor(columns / blockSizeC);
blockVectorC = [blockSizeC * ones(1, wholeBlockCols), rem(columns, blockSizeC)];
% Create the cell array, ca.
% Each cell (except for the remainder cells at the end of the image)
% in the array contains a blockSizeR by blockSizeC by 3 color array.
% This line is where the image is actually divided up into blocks.
if numberOfColorBands > 1
% It's a color image.
ca = mat2cell(rgbImage, blockVectorR, blockVectorC, numberOfColorBands);
else
ca = mat2cell(rgbImage, blockVectorR, blockVectorC);
end
percentBlack = cellfun(#(x)sum(sum(all(x == 0, 3))) / (numel(x) / size(x,3)), ca);
% Now display all the blocks.
plotIndex = 1;
numPlotsR = size(ca, 1);
numPlotsC = size(ca, 2);
for r = 1 : numPlotsR
for c = 1 : numPlotsC
fprintf('plotindex = %d, c=%d, r=%d\n', plotIndex, c, r);
% Specify the location for display of the image.
subplot(numPlotsR, numPlotsC, plotIndex);
ax2 = subplot(numPlotsR, numPlotsC, plotIndex);
% Extract the numerical array out of the cell
% just for tutorial purposes.
rgbBlock = ca{r,c};
imshow(rgbBlock); % Could call imshow(ca{r,c}) if you wanted to.
[rowsB columnsB numberOfColorBandsB] = size(rgbBlock);
set(ax2, 'box', 'on', 'Visible', 'on', 'xtick', [], 'ytick', []);
% Make the caption the block number.
averageBlack = percentBlack(r,c);
disp(numPlotsR);
disp(averageBlack);
caption = sprintf('Frame #%d of %d\n Percentage information content %0.2f', ...
plotIndex, numPlotsR*numPlotsC, averageBlack*100);
title(caption);
drawnow;
% Increment the subplot to the next location.
plotIndex = plotIndex + 1;
end
end
This line:
percentBlack = cellfun(#(x)sum(sum(all(x == 0, 3))) / (numel(x) / size(x,3)), ca);
specifically the part that says all(x == 0, 3) means "all color channels have value 0". You want to change it to "all color channels have value 1 (or 255 depends on your image)"
So basically, change that 0 to 1 or 255, deependinf if your image is unit8 or double

Applying SAD on image using matlab

Hello so I have an original image and I cropped a part of that image(template) and wrote a code with SAD algorithim to detect on the original image the part i cropped (template) where it exists and draw a rectangle on it.
The code doesnt have any errors , but the rectangle draw doesnt match the template , so I guess the 'output ' variable is the problem can you please help me
I2=imread('img.PNG');
I2=rgb2gray(I2);
[r,c]= size(I2);
%padding the image
%padding
B = padarray(I2,[24 24],'replicate' ,'both');
%imshow(B);
%creating template
temp=imread('crop_img.PNG');
temp= rgb2gray(temp);
%imshow(temp)
size(temp)
output = zeros (size(I2));
K = size(temp)
x=1;
y=1;
for i = 25 : r-24
for j = 25: c-24
%dif = temp -I2(i:i+47,j:j+47) ;
K = imabsdiff(temp,B(i-24:i+24,j-24:j+24));
output(i-24, j-24) = sum (K(:));
end
end
%gettting min value in output
min_value = output(1,1)
for i=1 : r
for j=1 :c
if(output(i,j)<min_value)
min_value=output(i,j);
row=i;
col=j;
end
end
end
row
col
output(1,465)
output(6,200)
%draw rectangle on matching area
%Create the shape inserter object.
shapeInserter = vision.ShapeInserter;
%Define the rectangle dimensions as [x y width height].
rectangle = int32([row col 24 24]);
%Draw the rectangle and display the result.
J = step(shapeInserter, I2, rectangle);
imshow(J);
There is an issue with image coordinates vs. matrix coordinates - you need to flip your row and column variables. Also, with shapeInserter, the coordinates are for the corner of the rectangle, so to make something centred on your output, you'd need something along the lines of:
rectangle = uint8([col-12 row-12 24 24]);
In MATLAB, it is usually not required to loop over every pixel of an image - it's much more efficient to work on the whole image at once. For example, you don't need a loop here:
min_value = output(1,1)
for i=1 : r
for j=1 :c
if(output(i,j)<min_value)
min_value=output(i,j);
row=i;
col=j;
end
end
end
This can be replaced by:
min_value = min(output(:));
[row,col] = find(output==min_value,1,'first');

Separating Background and Foreground

I am new to Matlab and to Image Processing as well. I am working on separating background and foreground in images like this
I have hundreds of images like this, found here. By trial and error I found out a threshold (in RGB space): the red layer is always less than 150 and the green and blue layers are greater than 150 where the background is.
so if my RGB image is I and my r,g and b layers are
redMatrix = I(:,:,1);
greenMatrix = I(:,:,2);
blueMatrix = I(:,:,3);
by finding coordinates where in red, green and blue the values are greater or less than 150 I can get the coordinates of the background like
[r1 c1] = find(redMatrix < 150);
[r2 c2] = find(greenMatrix > 150);
[r3 c3] = find(blueMatrix > 150);
now I get coordinates of thousands of pixels in r1,c1,r2,c2,r3 and c3.
My questions:
How to find common values, like the coordinates of the pixels where red is less than 150 and green and blue are greater than 150?
I have to iterate every coordinate of r1 and c1 and check if they occur in r2 c2 and r3 c3 to check it is a common point. but that would be very expensive.
Can this be achieved without a loop ?
If somehow I came up with common points like [commonR commonC] and commonR and commonC are both of order 5000 X 1, so to access this background pixel of Image I, I have to access first commonR then commonC and then access image I like
I(commonR(i,1),commonC(i,1))
that is expensive too. So again my question is can this be done without loop.
Any help would be appreciated.
I got solution with #Science_Fiction answer's
Just elaborating his/her answer
I used
mask = I(:,:,1) < 150 & I(:,:,2) > 150 & I(:,:,3) > 150;
No loop is needed. You could do it like this:
I = imread('image.jpg');
redMatrix = I(:,:,1);
greenMatrix = I(:,:,2);
blueMatrix = I(:,:,3);
J(:,:,1) = redMatrix < 150;
J(:,:,2) = greenMatrix > 150;
J(:,:,3) = blueMatrix > 150;
J = 255 * uint8(J);
imshow(J);
A greyscale image would also suffice to separate the background.
K = ((redMatrix < 150) + (greenMatrix > 150) + (blueMatrix > 150))/3;
imshow(K);
EDIT
I had another look, also using the other images you linked to.
Given the variance in background colors, I thought you would get better results deriving a threshold value from the image histogram instead of hardcoding it.
Occasionally, this algorithm is a little to rigorous, e.g. erasing part of the clothes together with the background. But I think over 90% of the images are separated pretty well, which is more robust than what you could hope to achieve with a fixed threshold.
close all;
path = 'C:\path\to\CUHK_training_cropped_photos\photos';
files = dir(path);
bins = 16;
for f = 3:numel(files)
fprintf('%i/%i\n', f, numel(files));
file = files(f);
if isempty(strfind(file.name, 'jpg'))
continue
end
I = imread([path filesep file.name]);
% Take the histogram of the blue channel
B = I(:,:,3);
h = imhist(B, bins);
h2 = h(bins/2:end);
% Find the most common bin in the *upper half*
% of the histogram
m = bins/2 + find(h2 == max(h2));
% Set the threshold value somewhat below
% the value corresponding to that bin
thr = m/bins - .25;
BW = im2bw(B, thr);
% Pad with ones to ensure background connectivity
BW = padarray(BW, [1 1], 1);
% Find connected regions in BW image
CC = bwconncomp(BW);
L = labelmatrix(CC);
% Crop back again
L = L(2:end-1,2:end-1);
% Set the largest region in the orignal image to white
for c = 1:3
channel = I(:,:,c);
channel(L==1) = 255;
I(:,:,c) = channel;
end
% Show the results with a pause every 16 images
subplot(4,4,mod(f-3,16)+1);
imshow(I);
title(sprintf('Img %i, thr %.3f', f, thr));
if mod(f-3,16)+1 == 16
pause
clf
end
end
pause
close all;
Results:
Your approach seems basic but decent. Since for this particular image the background is composed of mainly blue so you be crude and do:
mask = img(:,:,3) > 150;
This will set those pixels which evaluate to true for > 150 to 0 and false to 1. You will have a black and white image though.
imshow(mask);
To add colour back
mask3d(:,:,1) = mask;
mask3d(:,:,2) = mask;
mask3d(:,:,3) = mask;
img(mask3d) = 255;
imshow(img);
Should give you the colour image of face hopefully, with a pure white background. All this requires some trial and error.

Determine a regions average in MATLAB

I need some help with RGB capture in a image.
I am using impixel to manualy get RGB from a picture, but i would like to create a grid of let's say 20x20 px boxes where it will automatically tell me for each box a RGB value. So in a picture lets say i have 20 boxes it will tell me 20 RGB values. Yeah an if there is 20% or more of white space that it ignores that rgb box.
Can you point me to some links or give me a general idea how to do this.
Best regards
P.S. image is just a .jpg, the background is white an in the middle there is an item.
UPDATE
This is my code for collecting RGB using impixel
px=impixel(img);
st = num2cell(px,1);
zstup = cellfun(#sum,st);
zred = size(px,1);
rez = bsxfun(#rdivide,zstup,zred);
trez=round(rez);
What I want to do is :
http://imageshack.us/photo/my-images/696/exsample.jpg/
So every box like A1, A2, and so on will return RGB value like trez in my code.
So in my code i save my trez data in a table and it is like in excell lets say 220 | 23 | 34, now if i do that to another fruit i will have
220 | 23 | 34
123 | 212| 78
and so on...
Returning to automatization, A7 and A 15 would not be good RGB canditades because they have more then 50% white area so everything that has 20% white will be ignored.
So A31 is good and the RGB value needs to be saved.
So all in all here i would have my be 6 RGB values that would have to be automatically saved like the above example.
I know how to save to table i just need help for the gathering rgb values in every box.
Depending on your exact needs I see two solutions:
Downscale the image using impyramid(img, 'reduce'). This gives you a smaller image consisting of average values of the original image. Then do what you did before to access single pixels. Repeat as often as necessary to get 2x2, 4x4, 8x8 or larger "boxes".
Or you could use define a box (or arbitrary shape) as a matrix of ones and zeros and use the regionprops function in order to get information about the images content depending on the fields containing ones:
roi = zeros(size(img))
roi(1:10,1:10) = 1;
r = regionprops(roi, img, 'MeanIntensity')
average = r.MeanIntensity
This is my complete code for automatic color grabing from pictures in folder. So the program asks you to chose a folder and after that you get a table full of information about color and roundess. I am using this code to get color from fruits that have white background . It does everything by itself. Hope it helps someone.
clear all;
clc;
uiwait(msgbox('Chose the folder where your pictures are kept. Click OK to continue..'));
% Opening the folder
folder = uigetdir(pwd);
filePattern = fullfile(folder, '*.jpg');
jpegFiles = dir(filePattern);
for k = 1:length(jpegFiles)
baseFileName = jpegFiles(k).name;
fullFileName = fullfile(folder, baseFileName);
[pathstr, name, ext] = fileparts(fullFileName);
naziv_voca=name;
%Taking RGB color
slika = imread(fullFileName);
[redovi stupci RGBboje] = size(slika);
red_ink = floor(redovi/10);
stup_ink = floor(stupci/10);
r = 1;
c = 1;
for stupac = 1 : stup_ink : stupci
for red = 1 : red_ink : redovi
red1 = red;
red2 = red1 + red_ink;
stupac1 = stupac;
stupac2 = stupac1 + stup_ink;
red2 = min(red2, redovi);
stupac2 = min(stupac2, stupci);
crveniS = slika(red1:red2, stupac1:stupac2, 1);
zeleniS = slika(red1:red2, stupac1:stupac2, 2);
plaviS = slika(red1:red2, stupac1:stupac2, 3);
crvena(r,c) = mean2(crveniS);
zelena(r,c) = mean2(zeleniS);
plava(r,c) = mean2(plaviS);
r = r + 1;
if r >redovi
r = 1;
end
end
c = c + 1;
if c >1
c = 1;
end
end
RGB=[crvena,zelena,plava];
bijela=[255 255 255];
tolerancija = 50;
rez = RGB((abs(RGB(:,1)-bijela(1)) > tolerancija) | (abs(RGB(:,2)-bijela(2)) > tolerancija),:);
trez=round(rez);
%Taking shape
pic = rgb2gray(slika);
threshold = graythresh(pic);
bw = im2bw(pic,threshold);
fbw = ones(size(bw))-imfill(ones(size(bw))-bw);
invImg = ~fbw;
f = bwlabel(invImg);
S = regionprops(f,'Area','Perimeter','centroid');
Thr=100;
S=S([S.Area]>Thr);
score = (min(sqrt([S.Area]),[S.Perimeter]/4)./(max(sqrt([S.Area]), [S.Perimeter]/4))).^2;
score=max(score);
%Inserting data into table and creating data
if exist('tablica.mat','file')
vel=size(trez,1);
for z=1:vel
s=load('tablica');
olddata=s.data;
temp=trez(z,:);
dataCell= [naziv_voca,num2cell(temp),num2cell(score)];
data=[olddata;dataCell];
save('tablica.mat','-append','data');
end
else
stupac_rgb = num2cell(trez,1);
zstupac = cellfun(#sum,stupac_rgb);
zred = size(trez,1);
rez = bsxfun(#rdivide,zstupac,zred);
trez=round(rez);
data= [naziv_voca,num2cell(trez),num2cell(score)];
save('tablica','data')
end
end
uiwait(msgbox('Your information is saved'));

Resources