i am trying to read sprite/texture to get areas between blacklines in the first black and white photo. I don't know is it efficient but i am trying to do painting with numbers like in the third photo. I need to add numbers to all areas and i need to match the colors with original colored photo. Thanks.
[Black & White Image] (https://i.stack.imgur.com/JExFf.png)
[Colored Image] (https://i.stack.imgur.com/AVTax.jpg)
[Numbers Added] (https://i.stack.imgur.com/QAxRQ.png)
The basic algorithm you need is a 'flood fill' algorithm. Given a starting pixel, it will find all the pixels in a closed area. You would need to do this repeatedly until all the pixels in the image have been found.
There are lots of implementations for flood fill algorithms online.
So your routine could be something like-
Create an array of int's that stores which group each pixel is in. 0 means it's not been found yet.
Pick an unassigned pixel, and floodfill. Assign all the found pixels to a group.
Repeat 2 until all the pixels are assigned a group.
I do have different images which all have some kind of border around the "real" image. What I would like to achieve is to find the "real" image (size and location in pixels).
For me the challenge is that the border is not always black (can be any kind of black or grey with a lot of noise) and the "real" image (water with shark in this example) can have any combination of color, saturation, ...
Now in general I'm aware of algorithms like Canny, Blob detection, hough lines, ..., but I have just started using them. So far I managed to find the border for a specific image, but as soon as I try to apply the same algorithms and parameters to the next image it doesn't work. My current approach looks like this (pseudo code):
convert to gray CvInvoke.CvtColor(_processedImage, tempMat, CvEnum.ColorConversion.Rgb2Gray)
downsample with CvInvoke.PyrDown(srcImage, targetImage) and CvInvoke.PyrUp(srcImage, targetImage)
blur image with CvInvoke.GaussianBlur(_processedImage, bluredImage, New Drawing.Size(5, 5), 0)
Binarize with CvInvoke.Threshold(_processedImage, blackWhiteImage, _parameters.BinarizeThreshold, 255, CvEnum.ThresholdType.Binary)
Detect Edges with CvInvoke.Canny(_processedImage, imgEdges, 60, 100)
Find Contours with CvInvoke.FindContours(_processedImage, contours, Nothing, CvEnum.RetrType.External, CvEnum.ChainApproxMethod.ChainApproxSimple)
Assume that largest contour is the real image
I already tried different approaches based on for example:
Thresholding saturation channel and bounding box
Thresholding, canny edge and finding contours
Any hint especially on how to find proper parameters (that apply for all images) for algorithms like (adaptive) threshold and canny as well as ideas for improving the processing pipeline would be highly appreciated.
you can try to subtract black image from this image , and you will get the inside image , way to do this:
Use image subtraction to compare images in C# ,
If the border was uniform, this would be easy. Use cv::reduce to find MIN and MAX of each row and column; then count the top,left,bottom,right rows/columns whose MIN and MAX are equal (or very close) to the pixel value in a nearby corner. For sanity, maybe check the border colour is the same on all sides.
In your example the border contains faint red stuff, but a row/column approach might still be a useful way to simplify the problem. Maybe, as Nofar suggests, take an absolute difference with what you think is the background colour; square it, convert to grey, then reduce to Sums of rows and columns. You still need to find edges, but have reduced the data from two dimensions to one.
If there's a large border and lots of noise, maybe iterate: in the second pass, exclude the rows you think comprise the border, from statistics on columns (and vice versa).
EDIT: The above only works for an upright rectangle! If it could be rotated then the row/column projection method won't work. In that case I might go for sum-of-squared differences as above (don't start by converting to grey as it could throw away information), followed by blurring or some morphology, edge detection then some kind of Hough transform to find straight edges.
I'm working to a software that need a strange feature. I choose a png image like image attached and I need to place uniformly a certain number of points on black surface. I started with loop each pixel and change it's color to black, only for design, but now I need to think an algorithm to fill it with points (like 200 points (pixels with red color). You have a idea how to do this ?
Now in my mind is to count black pixels, then do something like this blackPixelsPerPoint = blackPixels / numberOfPoints. After this I now i need to have a red point every blackPixelsPerPoint.
The result need to be something like N letter
The points need to have almost same space between them and fill all the black surface if is possible (depend by number of points).
I have a collection of rectangles of varying sizes at different locations - we'll call this "Collection A".
The goal is to generate a secondary collection of fixed size rectangles (Collection B) that enclose all of the rectangles in Collection A. The rectangles in Collection B will have a fixed size of 2000x1000 pixels. I'm trying to optimize this so Collection B contains the smallest number of rectangles as possible.
In the drawing above the red rectangles represent Collection A. We're able to contain all of these within 3 fixed size rectangles.
A few rules:
All rectangles from Collection A must be contained fully within the bounds
of a rectangle from Collection B.
Collection B rectangles must always be 2000x1000 pixels.
Collection A rectangles will be sized somewhere between 50x50px and 1999x999px. Never wider than 1999px or taller than 999px.
Collection A rectangles will be distributed throughout an area several times the size of a Collection B rectangle.
A rectangle from Collection A is allowed to appear partially or fully within the bounds of multiple rectangles from Collection B, as long as rule 1 is met.
All rectangles from both collections will be axis parallel.
I'm sure there are examples of how to solve such a problem out there, but I'm not sure what this problem is called so my searches haven't turned up anything useful.
Assuming that it's OK for B-rectangles to overlap, then I would do the following. First, for each set of A-rectangles that can be covered by one B-rectangle, enumerate one such B-rectangle. We can slide the B-rectangle up and to the right until it rests against the edges of two A-rectangles, so all we have to do is collect the set of left x-coordinates and bottom y-coordinates from the A-rectangles and, for each element in the direct product, put the lower-left corner of a B-rectangle there.
Now, for each of these B-rectangles, determine the set of A-rectangles that it covers. Then convert the coverage problem to a set cover integer program and use an integer program solver to find the optimal solution.
Visual representation of the Point array (zoom to 800%): http://i.cubeupload.com/2Y3JPf.png
Please do not reupload to Imgur. Imgur's compression makes the image too blurry at high zooms.
(a zoomed in part of the image with the relevant dots highlighted:)
In the image, each red dot represents a Point. All the red dots combined represent the Point array. FYI, the Point array is ordered left to right, top to bottom. So pointArray[0] is in the top-left, pointArray[1] is in the top right, pointArray[2] is in the top-left but is also one line below pointArray[0] and pointArray[1].
As you can see, the majority of the red dots are in a grid but there are a couple of outliers in the top-left of the window and in the bottom-right where the number of mines are displayed. How would I get rid of the outliers? I've thought of parsing each point one by one to see if they are a constant number of pixels away from each other but at which point do I start? pointArray[0] is in the top-left so it's not even part of the grid which would mean that finding a constant pixel gap isn't going to work.
Any ideas?
Here is a method that should work for all grid sizes:
Count the number of dots in each row, and the number of dots in each column.
Then remove all dots in rows and columns that have less than the average number of dots.
You can construct such a histogram efficiently with a dictionary:
var numDotsPerRow = new Dictionary<int,int>();
var numDotsPerColumn = new Dictionary<int,int>();
foreach (var point in pointArray)
{
int count;
numDotsPerRow.TryGetValue(point.X, out count);
numDotsPerRow[point.X] = count+1;
numDotsPerColumn.TryGetValue(point.Y, out count);
numDotsPerColumn[point.Y] = count+1;
}