Paste several images into a bigger one, using conditions and loop (MATLAB) - image

I built a binary chessboard (tab):
Now I have to put in several pieces (pawns), just like this:
P_1 and P_2 have the same dimension that each block of the chessboard (301x301 px)
like it follows:
P_1 :
P_2:
In another exercise I had to invert the images of row 2, doing this:
P1_neg=double(P_1)*-1+255;
P2_neg=double(P_2)*-1+255;
I obtain this images:
P1_neg:
P2_neg
In the second row I have to paste two kind of pieces: a black pawn with black background (P_1), and a black pawn with white background (P_2).
Each block of the chessboard has 301x301 pixels, and each piece has the same measurements. I have to use only conditions and loops, but I don't know how paste the pieces there.
So, I know for the second row: when the row (i) it even and the column(j) is odd, I have to paste P_1; and when the row is even and the column is also even I have to paste P_2.
My code, is the following one, I hope you can help me :)
for i=1:8 % from 1 to 8 because it have 8 blocks
for j=1:8
if mod(i,2)==0 && mod (j,2)~=0
%paste P_1 (I don't know how do this)
elseif mod(i,2)==0 && mod(j,2)==0
%paste P_2
end
end
end
figure,imshow() % I don't know if I show the chessboard or I have to save the data in another matrix.
I couldn't upload the chessboard with the original resolution, but here it's the code I use
tab=zeros(2408);
for i=0:7
for j=0:7
if mod(i,2)~=0 && mod(j,2)~=0
for avanza_fila=(i*301)+1:(i+1)*301
for avanza_columna= (j*301)+1:(j+1)*301
tab(avanza_fila,avanza_columna)=255;
end
end
elseif mod(i,2)==0 && mod(j,2)==0
for avanza_fila=(i*301)+1:(i+1)*301
for avanza_columna= (j*301)+1:(j+1)*301
tab(avanza_fila,avanza_columna)=255;
end
end
end
end
end
figure, imshow(tab)

Here's my solution to your problem. I would personally avoid for loops, but you said your assignment needs it. I've created a high resolution version of your board that you can get here:
This board is 2408 x 2408, as each chess piece is 301 x 301, on an 8 x 8 grid. You almost have the logic correct. You just need to figure out how exactly to place the tiles on the board. I wrote two for loops where the first for loop uses rows 2 and 7, and the second for loop goes through columns 1 to 8. For either the second or seventh row, we check to see whether the column is even or odd and place the correct chess piece in its corresponding block. I also converted the board and the images to black and white to get rid of any quantization artifacts, as I saw that in the images you have posted. Also, I have renamed your images to how they're named in your post, so it'll be up to you to change the relevant names according to your code that you have written. I have also made a copy of the board in the code so that we don't want to modify the original board called boardCopy. This copy will contain the placed chess pieces in the board. Without further ado, here's the code:
board = imread('boardHigh.png'); %// High-res board
P_1 = im2bw(imread('P_1.png')); %// Load in the pawn pieces
P_2 = im2bw(imread('P_2.png'));
P1_neg = im2bw(imread('P1_neg.png'));
P2_neg = im2bw(imread('P2_neg.png'));
boardCopy = board; %// Make a copy of the board
for row = [2 7]
for col = 1 : 8
if row == 2
if mod(col,2) ~= 0
boardCopy((row-1)*301 + 1 : row*301, (col-1)*301 + 1 : col*301) = P_2;
else
boardCopy((row-1)*301 + 1 : row*301, (col-1)*301 + 1 : col*301) = P_1;
end
else
if mod(col,2) ~= 0
boardCopy((row-1)*301 + 1 : row*301, (col-1)*301 + 1 : col*301) = P1_neg;
else
boardCopy((row-1)*301 + 1 : row*301, (col-1)*301 + 1 : col*301) = P2_neg;
end
end
end
end
figure;
imshow(boardCopy);
This is the board I get with the chess pieces:
Hope this helps and good luck!

Related

Implementing the CCL (Connected Component Labeling) algorithm without the union-find data structure?

Hello fellow programmers!
A week ago I have been asigned the task of implementing the Connected Components Algorithm, mainly to extract the number of objects from an image.
You can read more about the algorithm here (https://en.wikipedia.org/wiki/Connected-component_labeling), the variant I am trying to implement is the two pass one.
This is my current attempt:
% ------------------------------------------------------------------------------
% -> Connected Component Labeling (CCL) Algorithm
% -> 4-Connectivity Version
% ------------------------------------------------------------------------------
% ------------------------------------------------------------------------------
% - [ Pre-Scan Code To Get Everything Ready ] -
% ------------------------------------------------------------------------------
% Starting With A Clean (Workspace) And (Command Window).
clear, clc;
% Instead Of Loading An Actual Image, We Are Creating A Matrix Of Zeros And Ones, Representing A Binary Image.
originalImage = [ ...
0 1 0
1 0 1
0 1 0 ];
% Creating A Bigger Matrix That We Will Use To Store The Original Image In Its Middle, This Will Help Us Eliminate Border Checking In The Raster Scan.
binaryImage = zeros(size(originalImage) + 2);
% Copying The Pixels From The Original Image Into The Middle Of The Larger Matrix We Created.
binaryImage(2:size(originalImage, 1) + 1, 2:size(originalImage, 2) + 1) = originalImage;
% Getting The Number Of Rows (Height) And Number Of Columns (Width) Of The Binary Image.
[imageRows, imageColumns] = size(binaryImage);
% Creating A Matrix The Same Dimensions As The Binary Image In Which The Labeling Will Happen.
labeledImage = zeros(imageRows, imageColumns);
% Creating A Label Counter That We Will Use To Assign When We Create New Labels.
labelCounter = 1;
% ------------------------------------------------------------------------------
% - [First Scan: Assigning Labels To Indices] -
% ------------------------------------------------------------------------------
% Going Over Each Row In The Image One By One.
for r = 1:imageRows
% Going Over Each Column In The Image One By One.
for c = 1:imageColumns
% If The Pixel Currently Being Scanned Is A Foreground Pixel (1).
if (binaryImage(r, c) == 1)
% Since We Are Working With 4-Connectivity We Only Need To Read 2 Labels, Mainly The (Left) And (Top) Labels.
% Storing Them In Variables So Referencing Them Is Easier.
left = labeledImage(r, c - 1);
top = labeledImage(r - 1, c);
% If Left == 0 And Top == 0 -> Create A New Label, And Increment The Label Counter, Also Add The Label To The Equivalency List.
if (left == 0 && top == 0)
labeledImage(r, c) = labelCounter;
labelCounter = labelCounter + 1;
% If Left == 0 And Top >= 1 -> Copy The Top Label.
elseif (left == 0 && top >= 1)
labeledImage(r, c) = top;
% If Left >= 1 And Top == 0 -> Copy The Left Label.
elseif (left >= 1 && top == 0)
labeledImage(r, c) = left;
% If Left >= 1 And Top >= 1 -> Find The Minimum Of The Two And Copy It, Also Add The Equivalent Labels To The Equivalency List, So We Can Fix Them In The Second Scan.
elseif (left >= 1 && top >= 1)
labeledImage(r, c) = min(left, top);
end
end
end
end
% ------------------------------------------------------------------------------
% - [Second Scan: Fixing The Connected Pixels But Mismatched Labels] -
% ------------------------------------------------------------------------------
for r = 1:imageRows
for c = 1:imageColumns
end
end
This first pass is going through without any issues, I have tried multiple tests on it, however I have no idea how to implement the second pass, in which I have to fix the equivalent labels in the labeled matrix.
I did do my research online, and the preferred way to do it is to use the union-find (disjoint set) data structure to store the equivalences between the labels.
However, since I am using MATLAB and the union-find data structure is not implemented, I have to implement it myself, which is cumbersome and requires massive time and hard work due to MATLAB being an interpreted language.
So, I am open to ideas on implementing the second pass without having to use the union-find data structure.
Thanks in advance!
If you don't want to use union-find, then you should really do the flood-fill-each-component algorithm (the other one in Wikipedia).
Union-find is neither difficult nor slow, however, and it's what I would use to solve this problem. To make a simple and fast implementation:
Use a matrix of integers the same shape as your image to represent the sets -- each integer in the matrix represents the set of the corresponding pixel.
An integer x represents a set as follows: If x < 0, then it is a root set of size -x. If x>=0 then it's a child set with parent set x (i.e., row x/width, column x%width)). Initialize all sets to -1 since they all start off as roots with size 1.
Use union-by-size and path compression

Determine subplot square dimensions from total number of plots

I'm trying to figure out how to calculate subplot dimensions when I know the total number of plots I need and I'd like the arrangement to be a square (with possibly a few empty subplots).
For example if I need 22 subplots then I would make a grid of 5x5 for a total of 25 subplots, then just leave three of them empty.
So I guess I'm looking for an algorithm where I'd input 22 and get out 5, for example. Anyone know of a short way to do this in python (maybe lambda function if possible)?
(Also open to other alternatives or pre-made solutions for doing this, I'm doing multiple subplot matrices for a dictionary of pandas dataframes)
This should work for what you're trying to do. I haven't tried anything with a lambda function but I doubt it would be difficult to modify this. There won't be any empty plots because the algorithm stops once it's out of values to plot.
I broke up the dictionary into key and value lists because I was originally working with lists when I wrote this. Everything up to the try clause would work without converting your values to a list. If you wanted to fill in with empty plots rather than using the somewhat hack-y break_test bit, you can put all of your code for the subplots inside a try clause.
Weird break version:
fig = plt.figure()
# Makes organizing the plots easier
key_list, val_list = [k, v for k, v in dict.getitems()]
# We take advantage of the fact that int conversions always round down
floor = int(np.sqrt(len(val_list))
# If the number of plots is a perfect square, we're done.
# Otherwise, we take the next highest perfect square to build our subplots
if floor ** 2 == len(val_list):
sq_chk = floor
else:
sq_chk = floor + 1
plot_count = 0
# The try/except makes sure we can gracefully stop building plots once
# we've exhausted our dictionary values.
for i in range(sq_chk):
for j in range(sq_chk):
try:
break_test = val_list[plot_count]
except:
break
ax = fig.add_subplot(sq_chk, sq_chk, plot_count + 1)
ax.set_title(key_list[plot_count])
...
# Whatever you want to do with your plots
...
plot_count += 1
plt.show()
No break version:
fig = plt.figure()
key_list, val_list = [k, v for k, v in dict.getitems()]
floor = int(np.sqrt(len(dict))
if floor ** 2 == len(dict):
sq_chk = floor
else:
sq_chk = floor + 1
plot_count = 0
# Everything from the original snippet should be nested in the try clause
for i in range(sq_chk):
for j in range(sq_chk):
try:
ax = fig.add_subplot(sq_chk, sq_chk, plot_count + 1)
ax.set_title(key_list[plot_count])
...
# Whatever you want to do with your plots
...
plot_count += 1
except:
plot_count +=1
plt.show()

Creating a checkerboard using Ruby and "\n" not disappearing

I feel as if I am close to a solution and have been tinkering around with this as a newb for some time. Why, for some reason, are my "\n"'s not disappearing when outputted for "next line" and the output has unneeded white space?
Task: Write a function which takes one parameter representing the dimensions of a checkered board. The board will always be square, so 5 means you will need a 5x5 board.
The dark squares will be represented by a unicode white square, while the light squares will be represented by a unicode black square (the opposite colors ensure the board doesn't look reversed on code wars' dark background). It should return a string of the board with a space in between each square and taking into account new lines.
An even number should return a board that begins with a dark square. An odd number should return a board that begins with a light square.
The input is expected to be a whole number that's at least two, and returns false otherwise (Nothing in Haskell).
I am close, and here is what I have so far:
def checkered_board(dimension)
black = "\u25A1 "
white = "\u25A0 "
checkboard = nil
checker_array = []
if dimension < 2 or dimension.is_a? String
return false
else
count = dimension
while count <= dimension && count > 0
if count % 2 == 0
checkboard = ("\u25A1 \u25A0" + "\n")
checker_array << checkboard
count -= 1
else
checkboard = ("\u25A0 \u25A1" + "\n")
checker_array << checkboard
count -= 1
end
end
end
checkboard = checker_array.join(" ")
p checkboard
end
Here is the TDD specs:
Test.assert_equals(checkered_board(0), false)
Test.assert_equals(checkered_board(2), "\u25A1 \u25A0\n\u25A0 \u25A1")
Note: Hidden specs demonstrate that it should respond with false if dimension is not an integer. .is_a? String and .is_a? Integer is not working for me too.
Output appears like so, and is not appearing even:
□ ■
■ □
Thanks for any and all help :).
Try changing:
if dimension < 2 or dimension.is_a? String
to
if !dimension.is_a?(Integer) || dimension < 2
The left most test will be done first. At the moment, if dimension is a String, it is first compared with 2 - which will raise an error - before it is tested as to whether it is a String. You need to check the type of object before you compare it with another object.
Also, I think the check should be whether dimension is not an Integer, rather than whether it is a String. For example, in your original code, what would happen if dimension was an Array?
The join method will concatenate the elements with a space character inserted between them. So this line from the program:
checkboard = checker_array.join(" ")
will result in this string:
"\u25A1 \u25A0\n \u25A0 \u25A1"
Omitting the argument to join should produce the expected output, ie.:
checkboard = checker_array.join
Refer to the documentation on the Array join method.

How do I quickly calculate changes in two n-by-4 matrices?

I have two matrices (tri1 and tri2) which represent a Delaunay triangulation. tri1 is the triangulation before inserting a new point, tri2 is the result after adding a new point. Each row has 4 columns. The rows represent tetrahedra.
I would like to calculate a relation between lines from tri1 to tri2. A result could look like this:
result =
1 1
2 2
3 3
4 4
0 0 % tri1(5, :) was not found in tri2 (a lot more lines could be missing)
6 5
7 6
8 7
9 8
10 9
Currently my source code looks like this:
% sort the arrays
[~, idx1] = sort(tri1(:, 1), 'ascend');
[~, idx2] = sort(tri2(:, 1), 'ascend');
stri1 = tri1(idx1, :);
stri2 = tri2(idx2, :);
result = zeros(size(tri1, 1), 2);
% find old cells in new triangulation
deleted = 0;
for ii = 1:size(tri1, 1)
found = false;
for jj = ii-deleted:size(tri2, 1)
if sum(stri1(ii, :) == stri2(jj, :)) == 4 % hot spot according to the profiler
found = true;
break;
end
if (stri1(ii, 1) < stri2(jj, 1)), break, end;
end
if found == false
deleted = deleted + 1;
else
result(idx1(ii), 1) = idx1(ii);
result(idx1(ii), 2) = idx2(jj);
end
end
The above source code gives me the results that I want, but not fast enough. I am not very experienced with MATLAB, I usually work with C++. My question: How can I speed up the comparison of two rows?
Some additional information (just in case):
the number of rows in tri can grow to about 10000
this function will be called once per inserted vertex (about 1000)
I cannot follow your example code completely, but judging from your explanation you want to see whether a row from matrix A occurs in matrix B.
In this case a very efficient implentation is available:
[Lia, Locb] = ismember(A,B,'rows');
Check the doc for more information about this function and see whether it is what you need.

Partition an image into 8 rows via Matlab, not all partitions shown

I wish to ask if anybody out there knows how to partition an image into 8 different rows and 1 column? I have tried using mat2cell() and using the demo on their wiki as a reference, I tried partitioning the image into 8 rows, however not all image partition rows are displayed.
If you see the image below, 2, 4, 6, 8 is not displayed. I am also not sure why is it of 16 blocks.
Can somebody help me check my code? I am not really used to the MatLab syntax and language. I trying my best to understand now.
My code for splitting the blocks are as follows:
blockSizeR = 50; % Rows in block.
blockSizeC = 512; % Columns in block.
wholeBlockRows = floor(rows / blockSizeR);
blockVectorR = [blockSizeR * ones(1, wholeBlockRows), rem(rows, blockSizeR)];
wholeBlockCols = floor(columns / blockSizeC);
blockVectorC = [blockSizeC * ones(1, wholeBlockCols), rem(columns, blockSizeC)];
if numberOfColorBands > 1
% It's a color image.
ca = mat2cell(rgbImage, blockVectorR, blockVectorC, numberOfColorBands);
else
ca = mat2cell(rgbImage, blockVectorR, blockVectorC);
end
% 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, 1, 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);
% Make the caption the block number.
caption = sprintf('Block #%d of %d\n%d rows by %d columns', ...
plotIndex, numPlotsR*numPlotsC, rowsB, columnsB);
title(caption);
drawnow;
% Increment the subplot to the next location.
plotIndex = plotIndex + 1;
end
end
I am new to MatLab, so is there is a simpler method to do this that I missed out, please do suggest or better still, if there are references that I can refer to. Many thanks (:
If you know the dimensions of your matrix, you can do the math to figure out how to divide the number of rows into 4 equal parts:
e.g. If: size(rockinsMatrix) == [10 20] (a 10row x 20column) matrix,
then you could split it into a set of 4 sub-matrices, two with 3 rows, and 2 with 2 columns.
If you want the matrices in a cell array then you can do that at that time.
I managed to solve already, the error lies in the for loop. I changed the for r = 1 : numPlotsR into r = 1 : (number of rows I want) for c = 1 : numPlotsC into c= 1: 1(as I only want one column), and used subplot(8,1,k) or (8,2,k) where k is the plot index. Just answering this in case anybody encounter such problem in future and want to use my code as a reference. Cheers!

Resources