I'm looking for an algorithm to chunk a non-rectangle image (i.e. transparent image) into blocks of (for example) size 16x16 pixels. The blocks may be overlapping, but the goal is to get the smallest amount of blocks.
Example
Summary
Blocks must have equal sizes
Blocks may be overlapping
Smallest amount of rectangles is the goal
Thank you in advance
This is a special case of set cover. You could try an integer program solver, but there may just be too many possible blocks. The integer program would be amenable to column generation/branch and price, but that's an advanced technique and would require some experimentation to get it right.
I think that you could do pretty well with a greedy algorithm that repeatedly chooses the block covering as many pixels as possible including one boundary pixel.
Related
Been stuck on a problem for a while, hope some of you have ideas.
Given a matrix size N*M of binary values (0 / 1), come with an approach to return the number of 1's which is more efficient than simply iterating the matrix.
The key in my opinion is bitmap. Thought about allocating new N*M matrix and manipulate the two... haven't got a solution yet.
Any ideas?
From a theoretical point of view, unless the matrix has special properties, you must test all the N.M elements and this can be achieved by a loop. So this construction is optimal and unbeatable.
In practice, maybe you are looking for a way to get some speedup from a naïve implementation that handles a single element at a time. The answer will be highly dependent on the storage format of the elements and the processor architecture.
If the bits are packed 8 per bytes, you can setup a lookup table of bit counts for every possible byte value. This yields a potential speedup of x8.
If you know that the black zone are simply connected (no hole), then it is not necessary to visit their inside, a contouring algorithm will suffice. But you still have to scan the white areas. This allows to break the N.M limit and to reduce to Nw + Lb, where Nw is the number of white pixels, and Lb the length of the black outlines.
If in addition you know that there is a single, simply connected black zone, and you know a black outline pixel, the complexity drops to Lb, which can be significantly smaller than N.M.
Is there a convenient data structure for storing a pixel selection in a picture?
By pixel selection I mean a set of pixels you obtain with selection tools such as those in image editing software (rectangles, lasso, magic wand, etc.). there can be holes, and in the general case the selection is (much) smaller than the picture itself.
The objective is to be able to save/load selections, display the selected pixels only is a separate view (bounding box size), using selections in specific algorithms (typically algorithms requiring segmentation), etc. It should use as little memory space as possible since the objective is to store a lot of them in a DB.
Solutions I found so far:
a boolean array (size of the picture/8)
a list of (uint16,uint16) => unefficient if many pixels in the selection
an array of lists: lists of pixels series for each line
A boolean array will take W x H bits for the raster plus extra accounting (such as ROI limits). This is roughly proportional to the area of the bounding box.
A list of pixel coordinates will take like 32 bits (2x16 bits) per selected pixel. This is pretty large compared to the boolean array, except when the selection is very hollow.
Another useful representation is the run-length-encoding, which counts the continguous pixels row by row. This representation will take about 16 bits per run. Said differently, 16 / n bits per pixel when the average length of the runs is n pixels. This works fine for large filled shapes, but poorly for isolated pixels.
Finally, you can also consider just storing the outlines of the shapes as a list of pixels (32 bits per pixel) or as a Freeman chain (only 3 bits per pixel), which can be a significant saving with respect to the full enumeration.
As you can see, the choice is uneasy because the efficiency of the different representations is strongly dependent on the shape of the selection. Another important aspect is the ease with which the given representation can be used for the targeted processing of the selection.
I am new in image processing and I don't know the use of basic terms, I know the basic definition of sparsity, but can anyone please elaborate the definition in term of image processing?
Well Sajid, I actually was doing image processing a few months ago, and I had found a website that gave me what I thought was the best definition of sparsity.
Sparsity and density are terms used to describe the percentage of
cells in a database table that are not populated and populated,
respectively. The sum of the sparsity and density should equal 100%.
A table that is 10% dense has 10% of its cells populated with non-zero
values. It is therefore 90% sparse – meaning that 90% of its cells are
either not filled with data or are zeros.
I took this in the context of on/off for black and white image processing. If many pixels were off, then the pixels were sparse.
As The Obscure Question said, sparsity is when a vector or matrix is mostly zeros. To see a real world example of this, just look at the wavelet transform, which is known to be sparse for any real-world image.
(all the black values are 0)
Sparsity has powerful impacts. It can transform matrix multiplication of two NxN matrices, normally a O(N^3) operation, into an O(k) operation (with k non-zero elements). Why? Because it's a well-known fact that for all x, x * 0 = 0.
What does sparsity mean? In the problems I've been exposed to, it means similarity in some domain. For example, natural images are largely the same color in areas (the sky is blue, the grass is green, etc). If you take the wavelet transform of that natural image, the output is sparse through the recursive nature of the wavelet (well, at least recursive in the Haar wavelet).
I am looking for an algorithm which can split an image into smaller images, with some constraints.
One constraint is to use the least amount of "whitespace" meaning empty pixels. And the other is to specify a maximum amount of images to split it into.
For example lets look at the below image. There is a lot of "whitespace" in it. I would like to divide this images into a few other images so i can reduce the amount of memory this image occupies, and also to reduce the amount of "drawing" this image will take.
.=transparent pixel
x=colored pixel
....................
.xxxxxxxxxxx........
...xxxx...xxxxxx....
.............xxxxx..
...............xxx..
...............xxx..
....................
..xxxxxx............
.....xxxxxxxxxxx....
.........xxxxxxxxxx.
....................
Let's assume i want the image to be split into a maximum of 4 images, a possible sollution would be as drawn below.
....................
.111111111111111....
.111111111111111....
.............22222..
.............22222.
.............22222..
....................
..3333333...........
..33333334444444444.
.........4444444444.
....................
Does anyone have an algorithm for this, or knows the name of an algorithm which does this?
I have been looking for a while and found some related algorithms, but the algorithms i found don't account for the whitespace e.g. they split the image into rectangles covering only the non transparent pixels, resulting in a huge amount of rectangles.
The real life data i am working with are images of 1024*1024 pixels and i would prefer to reduce them into a maximum of 16 parts. the trick is to extract the 16 images using the least amount of whitespace.
I'd go with the same algorithm as ravloony, but with a slight and important modification, using a "crop" operation that looks for the minimal/maximal columns and rows that aren't completely empty and discarding the rest.
In practice, the crop operation would get a X*Y region as input and would output 4 integers - the coordinates of the smallest rectangle that contains all the used pixels of the region. This can also be used to detect and discard empty regions.
Example
....................
.xxxxxxxxxxx........ xxxxxxxxxxx.......
...xxxx...xxxxxx.... ..xxxx...xxxxxx...
.............xxxxx.. ............xxxxx.
...............xxx.. => ..............xxx. (first crop)
...............xxx.. ..............xxx.
.................... ..................
..xxxxxx............ .xxxxxx...........
.....xxxxxxxxxxx.... ....xxxxxxxxxxx...
.........xxxxxxxxxx. ........xxxxxxxxxx
....................
Now divide the image into NxN parts (using N=4 here) and use the crop operation on each of the parts:
xxxxx|xxxxx|x....|
..xxx|x...x|xxxxx|
---------------------
| | xxx|xx
| | ..x|xx
---------------------
| | x|xx
| | |
---------------------
xxxx|xx...| |
...x|xxxxx|xxxxx|
|...xx|xxxxx|xxx
For this example, we get 10+10+10+6+4+1+2+8+15+10+3=79 pixels instead of 21*11=231 which is only 34,2%. Note that this happens to be the same amount as with your handcrafted 4-part segmentation (30+15+14+20=79)!
Conclusions
Of course there will be some additional data to keep track of the position and size of the 16 parts for each and it won't always give best results, but I think it's a nice compromise between speed and savings and the algorithm is easy to write and maintain.
About the additional data: Images of size 1024x1024 and splitting into 4x4 parts would give you the possibility to use 4 byte values to store each rectangle, so additional data size would be only 16*4 = 64 bytes - regarding this, you should perhaps consider to increase your 16 part maximum unless it will slow down some other part like the drawing heavily.
Worst cases
Worst cases for this algorithm would be parts with some pixels at or near the edges set, like these:
x......x xxxxxxxx xx......
........ ........ x.......
........ ........ ........
x......x ...x.... .......x
Several solutions for these come to my mind:
Splitting the region again (ending up
with a quadtree implementation)
Using some additional step to detect
completely empty rectangles in the
inside.
Translating the grid that defines the parts a bit
I would look at doing it recursively, each time splitting in half or into four, until you get to the level you want (for you 2 -> 4^2 = 16). At the bottom level check for empty squares and discard them.
Of course this gives you a grid of rectangles proportional to the shape of the original image, rather than optimally placed rectangles, but it might start you off on the right track.
My gut says that an ideal solution is akin to the knapsack problem and is thus computationally impractical. You may be able to use some sort of heuristic to generate a "good-enough" solution.
You could use a flood-fill algorithm to select connected regions of non-transparent pixels. As a first cut, that would give you a rectangle for each disjoint area of color. If you have more rectangles available in your budget, you could try cutting them in different ways to see which gives you the highest "density" of colored pixels.
You want to write a run-lenght or a delta compression algorithm. Or you want to use a space-filing-curve or a spatial-index. A sfc recursively subdivide the surface into smaller 4 tiles and reduce the complexity of 2 dimension to 1 dimension thus it makes it easier to identify white-space. You want to look for Nick's hilbert-curve quadtree spatial index blog. You want to download my php class hilbert curve at phpclasses.org.
Sorry for the late comment but it took me some time to find a "good" algorithm.
After some research i am going for the following solution.
First i use a Quadtree and do a SplitAndMerge. i Split on "Whitespace" first. Then i am merging all the rectangles together into the largest area rectangles.
After that i sort the quadtree on area size, only keeping the largest x area's. (So essentialy keeping the largest whitespace areas). But i don't want the whitespace, i want everything except the whitespace so i invert the Quadtree, and do a SplitAndMerge Again. Then extracting the remaining rectangles out of the image, and binpacking them in the final image.
This has given me some excellent results, reducing the image size drastically (because my images had a lot of whitespace in it), and keeping the time to draw them to a minimum.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Background
Lego produces the X-Large Gray Baseplate, which is a large building plate that is 48 studs wide and 48 studs tall, resulting in a total area of 2304 studs. Being a Lego fanatic, I've modeled a few mosaic-style designs that can be put onto these baseplates and then perhaps hung on walls or in a display (see: Android, Dream Theater, The Galactic Empire, Pokemon).
The Challenge
My challenge is now to get the lowest cost to purchase these designs. Purchasing 2304 individual 1x1 plates can get expensive. Using BrickLink, essentially an eBay for Lego, I can find data to determine what the cheapest parts are for given colors. For example, a 1x4 plate at $0.10 (or $0.025 per stud) would be cheaper than a 6x6 plate at $2.16 (or $0.06 per stud). We can also determine a list of all possible plates that can be used to assemble an image:
1x1
1x2
1x3
1x4
1x6
1x8
1x10
1x12
2x2 corner!
2x2
2x3
2x4
2x6
2x8
2x10
2x12
2x16
4x4 corner!
4x4
4x6
4x8
4x10
4x12
6x6
6x8
6x10
6x12
6x14
6x16
6x24
8x8
8x11
8x16
16x16
The Problem
For this problem, let's assume that we have a list of all plates, their color(s), and a "weight" or cost for each plate. For the sake of simplicity, we can even remove the corner pieces, but that would be an interesting challenge to tackle. How would you find the cheapest components to create the 48x48 image? How would you find the solution that uses the fewest components (not necessarily the cheapest)? If we were to add corner pieces as allowable pieces, how would you account for them?
We can assume we have some master list that is obtained by querying BrickLink, getting the average price for a given brick in a given color, and adding that as an element in the list. So, there would be no black 16x16 plate simply because it is not made or for sale. The 16x16 Bright Green plate, however, would have a value of $3.74, going by the current available average price.
I hope that my write-up of the problem is succint enough. It's something I've been thinking about for a few days now, and I'm curious as to what you guys think. I tagged it as "interview-questions" because it's challenging, not because I got it through an interview (though I think it'd be a fun question!).
EDIT
Here's a link to the 2x2 corner piece and to the 4x4 corner piece. The answer doesn't necessarily need to take into account color, but it should be expandable to cover that scenario. The scenario would be that not all plates are available in all colors, so imagine that we've got a array of elements that identify a plate, its color, and the average cost of that plate (an example is below). Thanks to Benjamin for providing a bounty!
1x1|white|.07
1x1|yellow|.04
[...]
1x2|white|.05
1x2|yellow|.04
[...]
This list would NOT have the entry:
8x8|yellow|imaginarydollaramount
This is because an 8x8 yellow plate does not exist. The list itself is trivial and should only be thought about as providing references for the solution; it does not impact the solution itself.
EDIT2
Changed some wording for clarity.
Karl's approach is basically sound, but could use some more details. It will find the optimal cost solution, but will be too slow for certain inputs. Large open areas especially will have too many possibilities to search through naively.
Anyways, I made a quick implementation in C++ here: http://pastebin.com/S6FpuBMc
It solves filling in the empty space (periods), with 4 different kinds of bricks:
0: 1x1 cost = 1000
1: 1x2 cost = 150
2: 2x1 cost = 150
3: 1x3 cost = 250
4: 3x1 cost = 250
5: 3x3 cost = 1
.......... 1112222221
...#####.. 111#####11
..#....#.. 11#2222#13
..####.#.. 11####1#13
..#....#.. 22#1221#13
.......... 1221122555
..##..#... --> 11##11#555
..#.#.#... 11#1#1#555
..#..##... 11#11##221
.......... 1122112211
......#..# 122221#11#
...####.#. 555####1#0
...#..##.. 555#22##22
...####... 555####444 total cost = 7352
So, the algorithm fills in a given area. It is recursive (DFS):
FindBestCostToFillInRemainingArea()
{
- find next empty square
- if no empty square, return 0
- for each piece type available
- if it's legal to place the piece with upper-left corner on the empty square
- place the piece
- total cost = cost to place this piece + FindBestCostToFillInRemainingArea()
- remove the piece
return the cheapest "total cost" found
}
Once we figure out the cheapest way to fill a sub-area, we'll cache the result. To very efficiently identify a sub-area, we'll use a 64-bit integer using Zobrist hashing. Warning: hash collisions may cause incorrect results. Once our routine returns, we can reconstruct the optimal solution based on our cached values.
Optimizing:
In the example, 41936 nodes (recursive calls) are explored (searching for empty square top-to-bottom). However, if we search for empty squares left-to-right, ~900,000 nodes are explored.
For large open areas: I'd suggest finding the most cost-efficient piece and filling in a lot of the open area with that piece as a pre-process step. Another technique is to divide your image into a few regions, and optimize each region separately.
Good luck! I'll be unavailable until March 26th, so hopefully I didn't miss anything!
Steps
Step 1: Iterate through all solutions.
Step 2: Find the cheapest solution.
Create pieces inventory
For an array of possible pieces (include single pieces of each color), make at least n duplicates of each piece, where n = max(board#/piece# of each color). Therefore, at most n of that piece can cover all of the entire board's colors by area.
Now we have a huge collection of possible pieces, bounded because it is guaranteed that a subset of this collection will completely fill the board.
Then it becomes a subset problem, which is NP-Complete.
Solving the subset problem
For each unused piece in the set
For each possible rotation (e.g. for a square only 1, for a rectangle piece 2, for an elbow piece 4)
For each possible position in the *remaining* open places on board matching the color and rotation of the piece
- Put down the piece
- Mark the piece as used from the set
- Recursively decent on the board (with already some pieces filled)
Optimizations
Obviously being an O(2^n) algorithm, pruning of the search tree early is of utmost importance. Optimizations must be done early to avoid long-running. n is a very large number; just consider a 48x48 board -- you have 48x48xc (where c = number of colors) just for single pieces alone.
Therefore, 99% of the search tree must be pruned from the first few hundred plies in order for this algorithm to complete in any time. For example, keep a tally of the lowest cost solution found so far, and just stop searching all lower plies and backtrack whenever the current cost plus (the number of empty board positions x lowest average cost for each color) > current lowest cost solution.
For example, further optimize by always favoring the largest pieces (or the lowest average-cost pieces) first, so as to reduce the baseline lowest cost solution as quickly as possible and to prune as many future cases as possible.
Finding the cheapest
Calculate cost of each solution, find the cheapest!
Comments
This algorithm is generic. It does not assume a piece is of the same color (you can have multi-colored pieces!). It does not assume that a large piece is cheaper than the sum of smaller pieces. It doesn't really assume anything.
If some assumptions can be made, then this information can be used to further prune the search tree as early as possible. For example, when using only single-colored pieces, you can prune large sections of the board (with the wrong colors) and prune large number of pieces in the set (of the wrong color).
Suggestion
Do not try to do 48x48 at once. Try it on something small, say, 8x8, with a reasonably small set of pieces. Then increase number of pieces and board size progressively. I really have no idea how long the program will take -- but would love for somebody to tell me!
First you use flood fill to break up the problem into filling continuous regions of lego bricks. Then for each of those you can use a dfs with memoization you wish. The flood fill is trivial so I will not describe it farther.
Make sure to follow a right hand rule while expanding the search tree to not repeat states.
My solution will be:
Sort all the pieces by stud cost.
For each piece in the sorted list, try to place as many as you can in the plate:
Raster a 2D image of your design looking for regions of the image with uniform color, the shape of the current piece and free studs for each stud that the piece will use.
If the color of the region found do not exist for that particular piece, ignore an continue searching.
If the color exists: tag the studs used by that pieces and increment a counter for that kind of piece and that color.
Step 2 will be done once for squared pieces, twice for rectangular pieces (once vertical and once horizontal) and 4 times for corner pieces.
Iterate to 2 until the plate is full or no more type of pieces are available.
Once arrived to the end you will have the number of pieces of each kind and each color that you needed with a minimum cost.
If cost by stubs can change by color, then the original sorted list must include not only the type of piece by also the color.