find largest rectangle not (necessary) aligned with image boundary in binary matrix - arrays

I am using this solution to find rectangles aligned with the image border in a binary matrix. Suppose now I want to find a rectangle that is not aligned with the image border, and I don't know its orientation; what would be the fastest way to find it?
For the sake of the example, let's look for a rectangle containing only 1's. For example:
1 1 1 1 0 0 0 0 0 1 0 0 1 1 1
0 1 1 1 1 1 0 0 0 1 0 0 1 1 0
0 0 0 1 1 1 1 1 0 1 0 0 1 0 0
0 0 0 0 0 1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 1 1 0
Then the algorithm described in the solution I described above would only find a rectangle of size 6 (3x2). I would like to find a bigger rectangle that is tilted; we can clearly see a rectanble of at least size 10 or more...
I am working in C/C++ but an algorithm description in any language or pseudo-code would help me a lot.
Some more details:
there can be more than one rectangle in the image: I need the biggest only
the rectangle is not a beautiful rectangle in the image (I adapted my example above a little bit)
I work on large images (1280x1024) so I'm looking for the fastest solution (a brute-force O(n³) algorithm will be very slow)
(optional) if the solution can be parallellized, that is a plus (then I can boost it more using GPU, SIMD, ...)

I only have a partial answer for this question, and only a few thoughts on complexity or speed for what I propose.
Brute Force
The first idea that I see is to use the fact that your problem is discrete to implement a rotation around the center of the image and repeat the algorithm you already use in order to find the axis aligned solution.
This has the downside of checking a whole lot of candidate rotations. However, this check can be done in parallel since they are indepedant of one another. This is still probably very slow, although implementing it (shouldn't be too hard) and would provide a more definite answer to the question speed once parallelized.
Note that your work-space being a discrete matrix, there is only a finite number of rotation to browse through.
Other Approach
The second solution I see is:
To cut down your base matrix so as to separate the connected components [1] (corresponding to the value set you're interested in).
For each one of those smaller matrices -- note that they may be overlapping depending on the distribution -- find the minimum oriented bounding box for the value set you're interested in.
Still for each one of those, rotate your matrix so that the minimum oriented bounding box is now axis-aligned.
Launch the algorithm you already have to find the maximum axis-aligned rectangle containing only values from your value set.
The solution found by this algorithm would be the largest rectangle obtained from all the connected components.
This second solution would probably give you an approximation of the soluiton, but I believe it might prove to be worth trying.
For reference
The only solutions that I have found for the problem of the maximum/largest empty rectangle are axis-aligned. I have seen many unanswered questions corresponding to the oriented version of this problem on 2D continuous space.
EDIT:
[1] Since what we want is to separate the connected component, if there is a degree of overlap, you should do as in the following example:
0 1 0 0
0 1 0 1
0 0 0 1
should be divided into:
0 0 0 0
0 0 0 1
0 0 0 1
and
0 1 0 0
0 1 0 0
0 0 0 0
Note that I kept the original dimensions of the matrix. I did that because I'm guessing from your post it has some importance and that a rectangle expanding further away from the boundaries would not be found as a solution (i.e. that we can't just assume there are zero values beyond the border).
EDIT #2:
The choice of whether or not to keep the matrix dimensions is debatable since it will not directly influence the algorithm.
However, it is worth noting that if the matrices corresponding to connected components do not overlap on non-zero values, you may choose to store those matrices "in-place".
You also need to consider the fact that if you wish to return as output the coordinates of the rectangle, creating a matrix with different dimensions for each connected component, this will force you to store the coordinates of your newly created matrix in the original one (actually, one point, say for instance the up-left one, should be enough).

Related

2D array grouping 1's in C

2D array of 1s and 0s. How to label every group of 1s with a unique number?
I’m stuck on this problem for a while now. 1s can be grouped vertically, horizontally and diagonally. How can you go about solving this? For example,
0 0 1 1 0
0 1 1 0 0
0 0 0 0 1
0 0 0 1 0
Should be transformed to
0 0 x x 0
0 x x 0 0
0 0 0 0 y
0 0 0 y 0
x, y can be any unique numbers.
Appreciate it.
Here is what I have so far for iterative: https://i.imgur.com/oCmYC02.png
But the result is a bit off because it only checks for immediate adjacent 1's: https://i.imgur.com/DAtTBmM.png
Anyone have any idea how to fix this?
I'd do it like this:
Scan 2D array sequentially, row by row, column by column
If 1 found, use variation of the flood fill algorithm, which moves in 8 directions instead of 4, from that starting point (see normal 4-direction algorithm at https://en.wikipedia.org/wiki/Flood_fill), since you have diagonal example with "y", each time using new filler number.
Repeat 1 and 2 until no more ones left.

How to extract a 2D array from an image of the same array?

Is it possible to extract a 2D matrix from an image of the same? Having no related experience in this area, I am having trouble proceeding further.
For example, if the image of the array is this, the corresponding 2D array(with blanks denoted by 0) would be as follows:
5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 0 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 0 0 2 8 0
0 0 0 4 1 9 0 0 5
0 0 0 0 8 0 0 7 9
I would like to know some algorithm or software that would help me extract the array. As I have no prior experience, even a push in the right direction would be appreciated.
Background: I was working on a basic Sudoku solver using Java, and I have implemented the same with a basic backtracking algorithm. Now, instead of giving the input manually by typing out the 2D array, I want to obtain the same from an image of the array.
Image recognition is not as simple as it appear to be. A low quality picture of low resolution with shadows or with shiny parts brighter than the rest is hard to deal with. Let alone that 3D angle of the camera and 2D rotations in the image plane. All those factors should be diminished or eliminated before image recognition even start.
Assuming you have a clean input image with known width and height what you need is to chop the input image in several squares corresponding to matrix entries. Then for each small subimage run a number recognition algorithm.
For the first part, many times it is better to transform the image from 24bits rgb colors to 8-bits grayscale. In that way image pixels with almost the same color in rgb space will be clustered to have the same intensity in the 8bit grayscale space. Even binary image with only two intensities would be useful in this case. There are image treatment packages that can do it for you. Then chopping the image is not harder than doing 2D array manipulation.
For the second part you can discard all squares with same intensity as empty. For the nonempty squares you have to call a number recognition algorithm.
You can use many packages for pattern recognition out there such as OpenCV or specific OCR (optical character recognition) packages.
It is not hard to write your own feedforward neural network for that:
https://en.m.wikipedia.org/wiki/Feedforward_neural_network
See also:
Recognize numbers in images

Radial basis network character recognition

I want to develop a simple character recognition program by implementing a given neural network kind; a simple command line-type is enough.
The radial basis function neural network was assigned to me and I already studied the weight training, input-to-hidden-to-output procedures but I am still doubtful of in implementing it. My references are (1) and (2).
A simple one-dimensional array of a 10 by 10 binary object (that represents a character) is the input. For example, the array below
input = array(
0,0,0,1,1,1,1,0,0,0,
0,0,1,0,0,0,0,1,0,0,
0,1,0,0,0,0,0,0,1,0,
1,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,1 )
is the representation of the character "A":
0 0 0 1 1 1 1 0 0 0
0 0 1 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
I plan to take the total weight of the input and compare it to the training set as in the saved 1-D arrays of the other characters of the alphabet and the one with the closest is the prediction.
The problem is I tend to understand algorithms better if presented in a CLRS-manner or similar type as opposed to mathematical formula. I find it hard to understand the explanations in those two papers (which I find the easiest to read among others here in the Google search).
Can someone point me to a friendly algorithm for a RBNFF that takes in an array and produces an output of weights? If not, a paper that explains this in Layman's manner would be appreciated.
Training
For what I could find there is no "one right way" to train them.
The simplest training I could find was by a composition of two algorithms
(Clustering) Taking the left part (input weights and RBFs) of the network and doing unsupervised clustering. There is a few things you can try out hard/soft and the number of clusters/RBFs.
Each cluster is a representation of a single RBF with the weights connecting to it.
How you go from having clusters to get rbf and rbf weights depends on what clustering you are using. (I can extend this if it's unclear)
(Neural Network) The solving the left out part of the original RBFNN from the last step by using the output from the clustering as input to an ordinary single layer neural network.
Probably easier to find these more primitive algorithms easily explained
EDIT
found some "pseudo"-code with explanations that might explain it all better (written in C#)
http://msdn.microsoft.com/en-us/magazine/dn532201.aspx
(Supposedly) working python code
https://github.com/andrewdyates/Radial-Basis-Function-Neural-Network

Finding row with maximum no. of 1s if each row is sorted using logicalOR approach

Question similar to this may have been discussed before but I want to discuss a different approach to this.
Given a boolen 2D array where each row is sorted, find the rows with maximum number of 1s.
Input Matrix :
0 1 1 1
0 0 1 1
1 1 1 1
0 0 0 0
Output : 2
How about doing this approach...Logical OR for column 0 of each row and if answer is 1, return that row index and stop. Like in this case if I do (0 | 0 | 1 | 0) answer would be one and thereby return that row index. if the input matrix is something like :
Input matrix:
0 1 1 1
0 0 1 1
0 0 0 1
0 0 0 0
Ouput : 0
When I do logicalOR of column 0 of each row, answer would be zero...so I would move to column 1 of each row, the procedure is followed till the LogicalOR is 1.?I know other approaches to solve this problem but I would like to have view on this approach.
If it's:
0 ... 0 1
0 ... 0 0
0 ... 0 0
0 ... 0 0
0 ... 0 0
You'd have to search many columns.
The maximum amount of work involved would be linear in the number of cells (O(mn)), and the other approaches outperform this here.
Specifically the approach where:
You start at the top right and
Repeatedly:
Search left until you find a 0 and
Search down until you find a 1
And return the last row where you found a 1
Is linear in the number of rows plus columns (O(m + n)).
That would work since it's equivalent to finding the row for which the leftmost 1 is before (or at the same point as) any other row's leftmost 1. It would still be O(m * n) in the worst case:
Input Matrix :
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 1
Given that your rows are sorted, I would binary search for the position of the first one for each row, and return the row with the minimum position. This would be O(m * logn), although you might be able to do better.
Your approach is likely to be orders of magnitude slower than the naive "go through the rows, and count the zeros, and remember the row with the fewest zeros." The reason is that, assuming your bits are stored one-row-at-a-time, with the bools packed tightly, then memory for the row will be in cache all at once, and bit-counting will cache beautifully.
Contrast this to your proposed approach, where for each row, the cache line will be loaded, and a single bit will be read from it. By the time you've cycled through all the rows in your array, the memory for the first row will (probably, if you've got any reasonable number of rows), be out of the cache, and the row will have to be loaded again.
Approximately, assuming a 64B cache line, the first approach is going to need (1/64*8) memory accesses per bit in the array, compared to 1 memory access per bit in the array compared to yours. Since counting the bits and remembering the max is just a few cycles, it's reasonable to think that the memory access are going to dominate the running cost, which means the first approach will run approximately 64 * 8 = 512 times faster. Of course, you'll get some of that time back because your approach can terminate early, but the 512 times speed hit is a large cost to overcome.
If your rows are super-long, you may find that a hybrid between these two approaches works excellently: count the number of bits in the first cache-line's worth of data in each row (being careful to cache-line-align each row of your data in memory), and if every row has no bits set in the first cache-line, go to the second and so forth. This combines the cache-efficiency of the first approach with the early termination of the second approach.
As with all optimisations, you should measure results, and be sure that it's important that the code is fast. The efficient solution is likely to impose annoying restrictions (like 64-byte memory alignment for rows), and the code will be harder to read than a straightforward solution.

Check if 2d shape composed of block has been cut

I know that the title of this topic might be confusing, but I didn't know how to explain it in a single sentence!
I'll try to be more clear, I have a 2d array of boolean values, every value states if that particular position (or block) is alive or not.
Let's make an example:
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
This array contains 16 "alive" blocks, now I can "kill" some blocks, changing their state from 1 to 0.
What I would like to do is to know if after a "kill", the group splits in two or more separate groups, for example:
1 1 0 1
1 1 0 1
0 1 0 1
1 1 1 1
This shape is still "intact", since the group of 0 is not cutting any of the 1 groups, but in this case:
1 1 0 1
1 1 0 1
0 0 0 1
1 1 1 1
Now I've killed the only bit who was keeping all the 1 together, the shape has been divided in two smaller groups!
I've tried checking the neighbours of the last killed bit but then I can't be sure of other possible connection of the shape.
I've also tried a pathfinding algorithm but this operation should be very fast and a pathfinding is too complex.
How can I achieve this?
Pick any of the alive blocks and do a flood-fill and then check if it got to all the other live blocks.

Resources