Linearly convert color space of RGB image in Octave - octave

I have a 3x3 matrix used to linearly transform RGB colors. How can I convert the color space of an RGB image using that matrix? Should I loop through all the pixels and convert them one by one or does a faster way exist?

Assuming that your 3x3 matrix M is supposed to be multiplied with your pixel value p as follows:
new_p = M * p;
(with p a column vector), then you can transform your nxmx3 image matrix as follows:
m = 1920;
n = 1080;
img = rand(n, m, 3);
tmp = reshape(img, [], 3); % no copy made
tmp = tmp * M.';
new_img = reshape(tmp, n, m, 3);
Note that here we transformed M * p into p.' * M.', so that we don't need to transpose the image, which would require copying all its data to a new array. Transposing M is a lot cheaper than transposing tmp.
You can do the above in a single line, avoiding the need for the tmp array:
new_img = reshape(reshape(img, [], 3) * M.', n, m, 3);

Related

2D Plots of arrays. Plot CSV columns (a, b) Vs array Y ( n, m) as single figure

How can I Make a plot from an array value with range Y against data with 24 columns and row values(500, 24)?
Y=np.linspace[100,9300,115]
data_b = pd.read_csv('profiler.csv')
data = data_b.to_numpy()`
MAKE THE PLOT
fig, axs = plt.subplots(figsize=(17,5),sharey=False,ncols=1,dpi=200)`
axs=plt.subplot(111)
axs.plot(data,Y)
#[![The expected type of plot](https://i.stack.imgur.com/t7Zia.jpg)](https://i.stack.imgur.com/t7Zia.jpg) Plot
`axs.set_ylim(0,1000)
axs.set_xlim(0,24)
colorbar_label='Reflectivity (dBZ)'
plt.title('PLOT', fontsize=24)
plt.xlabel('Time', fontsize= 20)
plt.ylabel('Range (Km)', fontsize=20)
cbar=plt.colorbar()
cbar.set_label('(dBZ)', fontsize=15)
plt.show()`

Normalization of histogram in Octave by hist(y,x,norm)?

I was trying to normalize the histogram of uniformly distributed random numbers in the interval [0,10]. In octave documentation I came across the function as hist(y, x, norm) which I applied and got the histogram normalized in the interval. The code that I used is
m=input('Number of random numbers required = ')
v=10*rand(1,m)
hist(v,10,1,"facecolor", "b", "edgecolor", "w",'linewidth',1.5);
title(['Normalized histogram for ' num2str(m) ' uniformly distributed random numbers'])
set(gca,'fontsize',30)
but as I changed the bin number to 50 then for getting the normalized histogram I had to change the third argument of hist() to 5.
Here is the code
m=input('Number of random numbers required = ')
v=10*rand(1,m)
hist(v,50,5,"facecolor", "b", "edgecolor", "w",'linewidth',1.5);
title(['Normalized histogram for ' num2str(m) ' uniformly distributed random numbers'])
set(gca,'fontsize',30)
then only it produced a normalized histogram as the previous one. What's actually happening here? Why I need to change the norm argument to 5 when I changed the bin number to 50?
When I tried to normalize the gaussian distribution using same method I got it wrong ?( I had to do it write all the algorithm to get the correct answer) so I would like to know how the norm argument works ?
here is the code that i tried for gaussian distribution which yielded the wrong result
m=input('Number of random numbers required = ');
v=randn(1,m)
[f,x]=hist(v,50);
hold on;
g = 1 / sqrt(2 * pi) * exp(-0.5 * x .^ 2);
plot(x, g, 'r','linewidth',1.5);
hist(v,50,5,"facecolor", "b", "edgecolor", "w",'linewidth',1.5);
title(['Normalized histogram for ' num2str(m) ' gaussian distributed random numbers'])
set(gca,'fontsize',30)
The reason is because you are trying to compare a frequency histogram with a frequency DENSITY function. Which means you have not taken the effect of the bin width into account.
In other words, if we consider each value in v, which represents histogram height, to be the product of the bin width w and a 'density' value h such that v = h * w at each element, then your normalisation says that sum(v) = 1, and therefore sum(h * w) = w * sum(h) = 1.
Therefore in order to obtain a valid 'density' function from your current values, you need to divide your current values in v by the (constant) bin width w, to obtain the density value h.
Compare with this code:
m = 5000;
v = randn( m, 1 );
g = 1 / sqrt(2 * pi) * exp( -0.5 * x .^ 2 );
[nn,xx] = hist( v, 50, 1, 'facecolor', 'b', 'edgecolor', 'w', 'linewidth', 1.5);
nn = nn / diff(xx)(1);
bar( xx, nn, 0.5, 'facecolor', [0, 0.5, 1], 'edgecolor', [0, 0.25, 0.5] );
hold on;
plot(x, g, 'r','linewidth', 3);
title({ ['Normalized histogram for ', num2str(m)], ' gaussian distributed random numbers'})
set(gca,'fontsize',20)
hold off

Apply function with two inputs on every two last elements of array

Hi I have a 2d array looking this way
a = np.array[[12032, 12, 23, 12],[12032, 22, 12, 12]]
Where index 0 is ID, index 1 is x coordinate, index 2 is y coordinate and index 3 is z coordinate.
I have made a function that calculates the angle of the coordinate taking two inputs (length a, length b)
I want to apply this function with index 1 and 2 for each array element in the array and append the result in a new "column" in the array.
angle = np.empty((0))
for array in elements_in_selection:
nice = array
a = array[1]
b = array[2]
angle_element = angle_calculate(a,b)
angle = np.append(angle, np.array([angle_element]),axis=0)
angle = np.expand_dims(angle, axis=1)
elements_in_selection = np.append(elements_in_selection, angle, axis=1)

NxN detect win for tic-tac-toe

I have tried to generalise my tic-tac-toe game for an NxN grid. I have everything working but am finding it hard to get the code needed to detect a win.
This is my function at the moment where I loop over the rows and columns of the board. I can't figure out why it's not working currently. Thanks
def check_win(array_board):
global winner
for row in range(N):
for i in range(N-1):
if array_board[row][i] != array_board[row][i+1] or array_board[row][i] == 0:
break
if i == N-1:
winner = array_board[row][0]
pygame.draw.line(board, (0, 0, 0), (75, (row * round(height / N) + 150)), (825, (row * round(height / N) + 150)), 3)
for col in range(N):
for j in range(N-1):
if array_board[j][col] == 0 or array_board[col][j] != array_board[col][i+1]:
break
if j == N - 1:
winner = array_board[0][col]
pygame.draw.line(board, (0, 0, 0), (col * round(width / N) + 150, 75), (col * round(width / N) + 150, 825), 3)
You don't specify in your question, so my noughts-and-crosses grid is a 2D array of characters, with some default "empty" string (a single space).
def getEmptyBoard( size, default=' ' ):
""" Create a 2D array <size> by <size> of empty string """
grid = []
for j in range( size ):
row = []
for i in range( size ): # makes a full empty row
row.append( default )
grid.append( row )
return ( size, grid )
So given a 2D grid of strings, how does one check for a noughts-and-crosses Win? This would be when the count of the same character in a particular row or column is equal to the size of the grid.
Thus if you have a 5x5 grid, any row with 5 of the same item (say 'x') is a winner. Similarly for a column... 5 lots of 'o' is a win.
So given a 2D array, how do you check for these conditions. One way to do this is to tally the number of occurrences of separate symbols in each cell. If that tally reaches the 5 (grid size), then whatever that symbol is, it's a winner.
def checkForWin( board, default=' ' ):
winner = None
size = board[0]
grid = board[1]
### Tally the row and column
for j in range( size ):
col_results = {}
### Count the symbols in this column
for i in range( size ):
value = grid[i][j]
if ( value in col_results.keys() ):
col_results[ value ] += 1
else:
col_results[ value ] = 1
### Check the tally for a winning count
for k in col_results.keys():
if ( k != default and col_results[k] >= size ):
winner = k # Found a win
print("Winner: column %d" % ( j ) )
break
if ( winner != None ):
break
# TODO: also implement for rows
# TODO: also implement for diagonals
return winner # returns None, or 'o', 'x' (or whatever used for symbols)
The above function uses two loops and a python dictionary to keep a list of what's been found. It's possible to check both the row and columns in the same loops, so it's not really row-by-row or column-by-column, just two loops of size.
Anyway, so during the loop when we first encounter an x, it will be added to the dictionary, with a value of 1. The next time we find an x, the dictionary is used to tally that occurrence, dict['x'] → 2, and so forth for the entire column.
At the end of the loop, we iterate through the dictionary keys (which might be , o, and x) checking the counts. When the count is the same size as a row or column, it's a winning line.
Obviously if there's no win found, we zero the tally and move to the next column/row with the outer-loop.

Smallest distance between matrix and vector

I have a matrix with dimension NxM and one vector with length M. I need the smallest distance of all the distances between each row of the matrix and the single vector.
My approach was to create a second matrix using repmat and then calculate the distances between each row, but I am only getting the total distance:
matrix2 = repmat(vector, N, 1);
norm(matrix1 - matrix2, 2)
Let me show this with an example:
m = rand (5, 2); # Your matrix with reference points
v = rand (1, 2); # Your vector
tmp = bsxfun(#minus, m, v);
d = hypot (tmp(:,1), tmp(:,2)); # Difference between v and all rows in m
# Find samllest distance
[dmin, ix] = min (d)
# visualize it
scatter (m(:,1), m(:,2), 8, "red");
hold on
plot([v(1), m(ix, 1)], [v(2), m(ix, 2)], "-*")
hold off
print ("out.png")
The red bubbles are points in m (2D case) and the "*" one is v. A blue line connects v with the one from m, which ist nearest to.
I think on octave, you can use automatic broadcasting to get the distances without repmat-ing or using norm like so -
dist = sum((matrix1 - vector).^2,2)
On MATLAB, you can avoid repmat with bsxfun like this -
dist = sum(bsxfun(#minus,matrix1,vector).^2,2)
And, if you still like to continue with repmat, you can get the distances like so -
matrix2 = repmat(vector, N, 1);
dist = sum((matrix1 - matrix2).^2,2)
Finally, to get the smallest distance and the corresponding row index, you can use min -
[smallest_dist,minrow_ind] = min(dist)