Having Trouble Keeping Axes Fixed While Adding Images in MATLAB - image

I'm currently working on creating a GUI based BlackJack game in MATLAB. I set up two axes for the dealer hand and player hand as follows:
self.window = figure('Name', 'Blackjack',...
'Units', 'normalized',...
'Position', [.02, .05, .95, .85]);
self.dealerHand = axes('Parent', self.window,...
'XLimMode', 'manual',...
'XLim', [0, 10],...
'YLimMode', 'manual',...
'YLim', [0, 1],...
'Title', 'Dealer',...
'Units', 'normalized',...
'Position', [.05, .70, .90, .25]);
self.playerHand = axes('Parent', self.window,...
'XLimMode', 'manual',...
'XLim', [0, 10],...
'YLimMode', 'manual',...
'YLim', [0, 1],...
'Title', 'Player',...
'Units', 'normalized',...
'Position', [.05, .20, .90, .25]);
As you can see, I've set both "hands" XLim and YLim modes to manual. However, when I run this script:
bjWindow = BlackJackWindow;
deck = DeckOfCards;
deck.shuffle
playerHand{1} = deck.cards{1};
dealerHand{1} = deck.cards{2};
playerHand{2} = deck.cards{3};
dealerHand{2} = deck.cards{4};
hold on
image(bjWindow.dealerHand, [0, 1], [0, 1], dealerHand{1}.img)
image(bjWindow.dealerHand, [1, 2], [0, 1], dealerHand{2}.img)
hold off
hold on
image(bjWindow.playerHand, [0, 1], [1, 0], playerHand{1}.img)
image(bjWindow.playerHand, [1, 2], [1, 0], playerHand{2}.img)
hold off
the dealer "hand" auto resizes and stretches the second card like this:
If I reverse the order of the hands in the first block of code, the error happens in the player "hand." In other words, whichever axes is created first when the window is initialized has this error. Another question that isn't as important because I've found a workaround, is why does the player "hand" flip the axes such that I have to set the y position to [1, 0] instead of [0, 1]?

The hold on affects the current axes, which is the last one you made. When adding an image to the first axes you made, it will be reset. Inverting is part of that, as image inverts the y-axis when displaying an image.
The solution is to use
hold(bjWindow.dealerHand,'on')
hold(bjWindow.playerHand,'on')
I would recommend against turning the hold off again after plotting. There is no need.
Instead, to change what cards are displayed, replace the image object's CData property. This is where the pixel data is stored. By updating this property, instead of creating a new image object, your application will be smoother, and you won't need to worry about deleting and re-recreating image objects, preserving axes properties, etc. Updating the property is trivial since all your gliphs (I presume) are of the same sizes.
set(image_handle,'CData',playerHand{1}.img)

Related

Adding a second label to colorbar

I have an imshow plot with a colorbar. I want two labels in the colorbar, one on the left side and the other one on the right side.
This is the mve:
V = np.array([[1, 2, 3], [4, 5, 6]]) # Just a sample array
plt.imshow(V, cmap = "hot", interpolation = 'none')
clb = plt.colorbar()
clb.set_label("Firstlabel", fontsize=10, labelpad=-40, y=0.5, rotation=90)
#clb.set_label("SECONDLABEL") # This is the label I want to add
plt.savefig("Example")
This produces:
I want a second label on the right side of the colorbar. If I use the commented line a second colorbar is added to my plot, and that is not what I want. How can I do this?
You can't have two label objects, but you could add a second label using clb.ax.text.
Also, note that to move the first label to the left hand side, you could use clb.ax.yaxis.set_label_position('left') rather than labelpad=-40
So, using lines:
clb = plt.colorbar()
clb.set_label("Firstlabel", fontsize=10, y=0.5, rotation=90)
clb.ax.yaxis.set_label_position('left')
clb.ax.text(2.5, 0.5, "SECONDLABEL", fontsize=10, rotation=90, va='center')
Produces this figure:

Incorrect assignment of values in 2D list in python

I was trying to assign values to multi dimension list in python after initializing it to zeroes first.
Following is the code where edge_strength and initialProb are multiD list.
edge_strength = [[1,2,3],[3,4,5],[6,7,8]]
initialProb = [[0]*3]*3
initialColumn =1
denominator = 10
for r in range(0,3):
initialProb[r][initialColumn] = float(edge_strength[r][initialColumn])/denominator
print initialProb
But when I finished and printed initialProb list, I got answer as - [[0, 0.7, 0], [0, 0.7, 0], [0, 0.7, 0]]
Instead it should've been - [[0, 0.2, 0], [0, 0.4, 0], [0, 0.7, 0]].
Can anyone explain me this strange behaviour and the workaround?
I don't understand why you solution does not work either. It seems as if edge_strength[r][initialColumn] is broadcasted although initialProb[r][initialColumn] is a scalar. I would expect something similar if you instead wrote
initialProb[1] = float(edge_strength[r][initialColumn])/denominator
but like this it does not make sense.
Here is a workaround using numpy. numpy-arrays have the advantage, that multiple columns can be addressed at once. I hope that helps at least.
import numpy as np
initialProb = np.zeros((3,3))
edge_strength = np.array([[1,2,3],[3,4,5],[6,7,8]])
initialProb[:,initialColumn] = edge_strength[:,initialColumn].astype(np.float)/denominator
Edit: I understood what's going on. Refer to Python list multiplication: [[...]]*3 makes 3 lists which mirror each other when modified When you initialize initialProb you don't get three different rows, but three references to the same list. If you modify the list, all three are changed.
According to the thread
initialProb = [ [0]*3 for r in range(3) ]
should also solve your error

Automatic Level Generation from Array

So, I am trying to make the stages for the level in my game automatically generated.
I made an array (note, the amount of "tiles" on the screen is 16x16):
var background:Array=new Array(
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
)
And as you can probably tell, each 1 or 0 corresponds to if the tile is one thing or another (there or not there in this scenario).
I am pretty bad at the next part that I did.
I decided to make this using http://www.flashgametuts.com/tutorials/as3/how-to-create-a-platform-game-in-as3-part-2/'s method (kinda).
var bkgblocks:Sprite=new Sprite();
var bkgblocksw:Number=stage.stageWidth/16
var bkgblocksh:Number=stage.stageHeight/16
//the blocks are 45 pixels wide and tall
var row:int=0;
for(var i:int=0; i<background.length;i++){
if((i+1)/16==int((i+1)/16)){
//if i is divisible by 16
row++
}
if(background[i]==1){
bkgblocks.graphics.beginFill(0x000000)
bkgblocks.graphics.drawRect(I have no idea what to do here ,row*stage.stageHeight/16,bkgblocksw,bkgblocksh);
bkgblocks.graphics.endFill()
addChild(bkgblocks)
}
}
As you can see, I have no idea how or where to place the blocks!
I have where to place their y coordinate, but the x is way too confusing.
I thought I could do something like this
i*(45/(row+1))
but that messed up completely. This is more of a math question, I'm sorry, but if anybody can (or has) figure this out, I would appreciate it.
I usually prefer packing a grid into an array of arrays to make it more human-readable e. g.
var grid:Array = [
[0, 0, 1, 0, 0],
[0, 1, 0, 1, 0],
[1, 0, 0, 0, 1],
[0, 1, 0, 1, 0],
[0, 0, 1, 0, 0]
];
Where the first (outer) array contains rows of cells, each row represented by an array
So you can access a cell by calling grid[y][x] and find the 'real' coordinates by multiplying x and y by const CELL_SIZE
It seems you are tangled with 1D-2D coordinate transformation.
Let's width of your screen (2D coordinates) is Wdt. So element with (x,y) coordinates will be at y * Wdt + x index of 1D array.
A[y * Wdt + x] corresponds to Screen[y][x]
And back tranform:
x = index %% Wdt //integer modulus
y = index \ Wdt //integer division
Screen[index \ Wdt] [index %% Wdt] = A[index]

Behaviour of max pooling is confused in Tensorflow

I am trying to reduce the resolution of an image to speed up training. So I used tf.nn.max_pool method to operate on my raw image. I am expecting the resultant image is a blurred one with smaller size, but actually it is not.
My raw image has shape [320, 240, 3], and it looks like:
And after max_pooling, with ksize=[1,2,2,1] and strides=[1,2,2,1] it becomes
produced by the following code:
# `img` is an numpy.array with shape [320, 240, 3]
# since tf.nn.max_pool only receives tensor with size
# [batch_size, height,width,channel], so I need to reshape
# the image to have a dummy dimension.
img_tensor = tf.placeholder(tf.float32, shape=[1,320,240,3])
pooled = tf.nn.max_pool(img_tensor, ksize=[1,2,2,1], strides=[1,2,2,1],padding='VALID')
pooled_img = pooled.eval(feed_dict={img_tensor: img.reshape([1,320,240,3])})
plt.imshow(np.squeeze(pooled_img, axis=0))
The pooled image has shape [160, 120, 3] which is expected. Its just the transformation behaviour is really confused me. It shouldnt have that "repeated shifting" behaviour, since there is no pixel overlapping computation.
Many thanks in advance.
I think the problem is how your image has been reshaped. This image actually has the shape of [240, 320, 3].
So try to use [1, 240, 320, 3]) instead of [1, 320, 240, 3]). It should work.

Matlab hist function for image data

I'm new to Matlab and I want to make my own function that makes the same job as imhist(Displays histogram of image data) but I am a total newbie to this and I don't have any clues how I'm going to develop such function..
I started making something but its very incomplete.
function [ output_args ] = myhist( x )
%MYHIST Summary of this function goes here
%Detailed explanation goes here
x=imread('flower.jpg');
imshow(x);
[c,d]=hist(x(:),0:1:255);
figure,plot(d,c);
figure,plot(c,d);
%figure,imhist(x);
end
I would be very grateful if you could give me any helpful tips..
Here is my attempt at implementing the IMHIST function. It does not handle all the cases that the official function does, but it should produce very similar results in most cases:
function myimhist(img)
img = im2uint8(img);
[count,bin] = hist(img(:), 0:255);
stem(bin,count, 'Marker','none')
hAx = gca;
set(hAx, 'XLim',[0 255], 'XTickLabel',[], 'Box','on')
%# create axes, and draw grayscale colorbar
hAx2 = axes('Position',get(hAx,'Position'), 'HitTest','off');
image(0:255, [0 1], repmat(linspace(0,1,256),[1 1 3]), 'Parent',hAx2)
set(hAx2, 'XLim',[0 255], 'YLim',[0 1], 'YTick',[], 'Box','on')
%# resize the axis to make room for the colorbar
set(hAx, 'Units','pixels')
p = get(hAx, 'Position');
set(hAx, 'Position',[p(1) p(2)+26 p(3) p(4)-26])
set(hAx, 'Units','normalized')
%# position colorbar at bottom
set(hAx2, 'Units','pixels')
p = get(hAx2, 'Position');
set(hAx2, 'Position',[p(1:3) 26])
set(hAx2, 'Units','normalized')
%# link x-limits of the two axes
linkaxes([hAx;hAx2], 'x')
set(gcf, 'CurrentAxes',hAx)
end
Let's test it with a sample image:
I = imread('coins.png');
figure(1), myimhist(I), title('myimhist')
figure(2), imhist(I), title('imhist')
Note how IMHIST is apparently adjusting the y-limit so as to deal with the two different peaks in the histogram.
I am not sure if I understand your goal. Try replacing
figure,plot(d,c);
with
figure,bar(d,c);

Resources