Short intro: I am working on a 3D laserscanning device, that creates a point cloud using pictures of an object which is illuminated by the laser.
Each picture shows essentially a line which represents the objects surface.
What I do then is store the value of brightness of each pixel in a 2D Array, which in the end results in a Matrix that puts a number on the position of the illuminated line. This I can take to further calculate the point cloud. All of this I'm doing in C++.
Now to the problem at hand:
After storing the brightness information inside the matrix, I get a complex line which is several pixels thick (thickness not uniform). I need it to be exactly 1 Pixel wide. Up until now I calculated either the mean value of the line, or used a weight function.
This only works well as long as your line mostly runs vertically or horizontally throughout the picture/matrix, because you can calculate the right value for each seperate line or column.
I have now pictures/matrices where the line has a more complex shape, so these simple solutions won't work anymore. Here are two examples:
How can I calculate the mean value or put a weight function on these lines, so i can bring them down to a thickness of 1px? I need an algorithm that does this automatically because I have sets of hundreds of pictures, where this line can be differently shaped, so it would be too timeconsuming/impossible to edit all of them seperately.
I hope I somehow talked sense rather then complicate things ;)
Related
I hope you are doing well. I am stuck at one part of a visual effect program in C++, and wanted to ask for help.
I have an array of colors at random positions on an image. There can be any number of these "subpixels" that fall over top of any given pixel. The subpixels that overlap a pixel can be at any position within the pixel, since they're distributed randomly throughout the image. All I have access to is their position on the image and their color, which represents what the color should be at that precise subpixel point on the image.
I need to determine what color to make each pixel of the image. In other words, I need to interpolate what the color should be at the centre of each pixel.
Here is a diagram with an example of this on a 5x5 image:
I need to go from this:
To this:
If it aids your understanding, you can think of the first image as a series of random points whose color values were calculated using bilinear interpolation on the second image.
I am writing this in C++, and ideally it will be as fast as possible, but I welcome contributions in any language or just explained with symbols or words. It should be as accurate as possible, but I also welcome solutions that are slightly inaccurate in favour of performance or simplicity.
Please let me know if you need clarification on the problem.
Thank you.
I ended up finding quite a decent solution which, while it doesn't find the absolutely 100% technically correct color for each pixel, was more than good enough and acceptably fast, especially when I added multithreading.
I first create a vector for each pixel/cell that contains pointers to subpixels (points with known colors). When I create a subpixel, I add a pointer to it to the vector representing the pixel/cell that it overlaps and to each of the vectors representing pixels/cells directly adjacent to the pixel/cell that that it overlaps.
Then, I split each pixel/cell into n sub-cells (I found 8 works well). This is not as expensive as you might imagine, because I only have to calculate & compare the distance for those subpixels that are in that pixel/cell's subpixel pointer vector. For each sub-cell, I calculate which subpixel is the closest to its centre. That subpixel's color then contributes 1/nth of the color for that pixel/cell.
I found it was important to add the subpixel pointers to adjacent cell/pixel vectors, so that each sub-cell can take into account subpixels from adjacent pixels/cells. This even makes it produce a reasonable color when there are pixels/cells that have no subpixels overlapping them (as long as the neighboring pixels/cells do).
Thanks for all the comments so far; any ideas about how to speed this up would be appreciated as well.
I'm working on a graphical application in C++ using Direct2d (DirectX11). The application takes in sensor data and displays the input using rectangles that are placed side-by-side across the x-axis (which represents time). Each rectangle is filled with a linear gradient brush that represents multiple sensor readings at the discrete time interval displayed along the y-axis.
When a reading is acquired, the placement for the starting 'x' position of the next rectangle should be exactly where the last one finished i.e. rect1.right should be rect2.left. The start point for each rect is calculated using the pseudocode below:
//find the number of rectangles needed to represent the time scale (rects must be an integer, as we cannot display partial rectangles
int nNumXRects = fAxisLength/fTimeDivision;
//calculate the X-axis increment for each rectangle
float fXIncrement = fXAxisLineLength/(float)NumXRects;
//Get the next x position
rect2.left = rect1.right;
rect2.right = rect2.left + fXIncrement;
My problem is that the graph only appears correctly when the value of fXIncrement is exactly a whole number e.g. 3.0f. This obviously restricts the length of the X-Axis to figures that are multiples of the number of rectangles, times the length of each rectangle. This affects the area available to all the other elements of the application.
If the value of the increment is anything other that a whole number, small black lines appear between the rectangles which destroys the appearance and makes the data much harder to interpret. I realise why this is happening in principle - we cannot display a fraction of a pixel for instance, but how should this be done properly so that the rectangles will always match up exactly, regardless of the length of the axis? It would seem that Direct2D is perfect for this and should intrinsically cope with mapping fractional values to physical pixels exactly, but I don't know what the correct approach is beyond by current simplistic solution which is to keep the length of the x-axis fixed (meaning I cannot scale properly and other elements do not have enough space in the horizontal).
Any pointers in the right direction would be much appreciated!
Can't this be fixed by setting the appropriate anti alias mode when drawing the rectangles?
pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
I've been trying to do something that seems surprisingly challenging --- printing an equilateral triangle to the command line (Terminal for Mac OS X). I have a program that can compute the nth row of Pascal's triangle up to some user-specified constant. As is well known, if one takes the values of Pascal's triangle modulo two, there is a correlation between that and Sierpinski's triangle.
I have been setting odd values to be 1 and even values to be 0, and when I print the results on the Terminal and zoom out, it looks nice, apart from the fact that it's clearly not equilateral. Here is an example output of my program after zooming way out (so zeroes and ones look much different):
But I'm wondering ... is there a way to get this triangle to look equilateral? Or do I have to print the output somewhere else? I've been experimenting with different fonts, different line width levels, but I can't get anything to look close to equilateral, and even if it does, I don't have a reliable way of checking for this. Part of the problem is also that zooming in/out on the Terminal results in different line width and height scales.
My code takes in as input the number of rows to generate. Then, it takes that number into account when printing out each row. So the first row (which is just a single "1") would have n-1 spaces to print before printing the 1. Then the second row has to print n-2 spaces before printing its actual contents (which are "1 1"), which includes a space between each number, and so on. It's in C++, but I don't think that should matter.
I suspect that I'll need to find some other way of getting the image out, so any advice about libraries to use would be great.
A good option is to render the triangle to an raster format of your choice, and use aalib or libcaca to render that image to the terminal.
I would try to (and I think you already have) figure out the actual width and height of what the image would ultimately be, and generate the 2D matrix defining that images dimensions. This matrix can be a 2D set of integers (no less than 24 bits wide giving space for 8 bit color components), or 3 separate 2D matrices, one for each color component. Set all of those values to whatever you want the background color to be.
Move through your algorithm setting the appropriate pixels to whatever OTHER color your want your actual triangle to show up as.
Look here for writing such a matrix out to a .bmp (or bitmap) file.
Writing BMP image in pure c/c++ without other libraries
I'm a student, and I've been tasked to optimize bilinear interpolation of images by invoking parallelism from CUDA.
The image is given as a 24-bit .bmp format. I already have a reader for the .bmp and have stored the pixels in an array.
Now I need to perform bilinear interpolation on the array. I do not understand the math behind it (even after going through the wiki article and other Google results). Because of this I'm unable to come up with an algorithm.
Is there anyone who can help me with a link to an existing bilinear interpolation algorithm on a 1-D array? Or perhaps link to an open source image processing library that utilizes bilinear and bicubic interpolation for scaling images?
The easiest way to understand bilinear interpolation is to understand linear interpolation in 1D.
This first figure should give you flashbacks to middle school math. Given some location a at which we want to know f(a), we take the neighboring "known" values and fit a line between them.
So we just used the old middle-school equations y=mx+b and y-y1=m(x-x1). Nothing fancy.
We basically carry over this concept to 2-D in order to get bilinear interpolation. We can attack the problem of finding f(a,b) for any a,b by doing three interpolations. Study the next figure carefully. Don't get intimidated by all the labels. It is actually pretty simple.
For a bilinear interpolation, we again using the neighboring points. Now there are four of them, since we are in 2D. The trick is to attack the problem one dimension at a time.
We project our (a,b) to the sides and first compute two (one dimensional!) interpolating lines.
f(a,yj) where yj is held constant
f(a,yj+1) where yj+1 is held constant.
Now there is just one last step. You take the two points you calculated, f(a,yj) and f(a,yj+1), and fit a line between them. That's the blue one going left to right in the diagram, passing through f(a,b). Interpolating along this last line gives you the final answer.
I'll leave the math for the 2-D case for you. It's not hard if you work from the diagram. And going through it yourself will help you really learn what's going on.
One last little note, it doesn't matter which sides you pick for the first two interpolations. You could have picked the top and bottom, and then done the third interpolation line between those two instead. The answer would have been the same.
When you enlarge an image by scaling the sides by an integral factor, you may treat the result as the original image with extra pixels inserted between the original pixels.
See the pictures in IMAGE RESIZE EXAMPLE.
The f(x,y)=... formula in this article in Wikipedia gives you a method to compute the color f of an inserted pixel:
For every inserted pixel you combine the colors of the 4 original pixels (Q11, Q12, Q21, Q22) surrounding it. The combination depends on the distance between the inserted pixel and the surrounding original pixels, the closer it is to one of them, the closer their colors are:
The original pixels are shown as red. The inserted pixel is shown as green.
That's the idea.
If you scale the sides by a non-integral factor, the formulas still hold, but now you need to recalculate all pixel colors as you can't just take the original pixels and simply insert extra pixels between them.
Don't get hung up on the fact that 2D arrays in C are really 1D arrays. It's an implementation detail. Mathematically, you'll still need to think in terms of 2D arrays.
Think about linear interpolation on a 1D array. You know the value at 0, 1, 2, 3, ... Now suppose I ask you for the value at 1.4. You'd give me a weighted mix of the values at 1 and 2: (1 - 0.4)*A[1] + 0.4*A[2]. Simple, right?
Now you need to extend to 2D. No problem. 2D interpolation can be decomposed into two 1D interpolations, in the x-axis and then y-axis. Say you want (1.4, 2.8). Get the 1D interpolants between (1, 2)<->(2,2) and (1,3)<->(2,3). That's your x-axis step. Now 1D interpolate between them with the appropriate weights for y = 2.8.
This should be simple to make massively parallel. Just calculate each interpolated pixel separately. With shared memory access to the original image, you'll only be doing reads, so no synchronization issues.
I'm relatively new to OpenCV, and I'm working on a project where I need to count the number of objects on a grid. the grid is the background of the image, and there's either an object in each space or there isn't; I need to count the number present, and I don't really know where to start. I've searched here and other places, but can't seem to find what I'm looking for. I will need to be tracking the space numbers of the grid in the future, so I will also eventually need to know whether each grid space is occupied or empty. I'm not going so far as to ask for a coded example, but does anybody know of any source or tutorials to accomplish this task or one similar to it? Thanks for your help!
Further Details: images will come from a stable-mounted camera, objects are of relatively uniform shape, but varying size and color.
I would first answer a few questions:
Will an object be completely enclosed in a grid cell? Or can it be placed on top of a grid line? (In other words, will the object hide a line from the camera?)
Will more than one object be in one cell?
Can an object occupy more than one cell? (closely related to question 1)
Given reasonable answers to those questions, I believe the problem can be broken into two parts: first, identify the centers of each grid space. To count objects, you can then sample that region to see if anything "not background" is there.
You can then assume that a grid space is defined by four strong, regularly-placed, corner features. (For the sake of discussion, I'll assume you've performed the initial image preparation as needed: histogram equalization, gaussian blur for noise reduction, etc.) From there, you might try some of OpenCV's methods for finding corners (Harris corner detector, cvGoodFeaturesToTrack, etc). It's likely that you can borrow some of the techniques found in OpenCV's square finding example (samples/c/square.c). For this task, it's probably sufficient to assume that the grid center is just the centroid of each set of "adjacent" (or sufficiently near) corners.
Alternatively, you might use the Hough transform to identify the principal horizontal and vertical lines in the image. You can then determine the intersection points to identify the extents of each grid cell. This implementation might be more challenging since inferring structure (or adjacency) from "nearby" vertices in order to find a grid center seems more difficult.