Merging two labels in connect components during the first pass - image-processing

In connected components labeling, if I see that the pixel to the left and the pixel above the current pixel have the same color but different labels, can't I automatically reassign their labels to be the same (instead of doing with an equivalence table)?
Wikipedia and MathWorks assigns the minimum label to the current pixel but otherwise leave the neighboring pixels the same. Then, they polish the label table with another pass. Unless I'm mistaken my tweak will allow me to label the image uniformly in a single pass. Is there an example in which my little tweak will break the algorithm?

You wouldn't eliminate the second pass. If you did change the labels of the neighboring pixels, what about their neighboring pixels? Basically, if this event happens, you've discovered the two labels are in the same equivalence class; but you'd still have to walk over everything you've examined so far to reassign those labels. You may as well just do that on the second pass and do all the reassigning in one sweep.
Example:
+-+-+-+
|?|?|A|
+-+-+-+
|B|B|x|
+-+-+-+
You examine pixel x, it matches both pixels north and west. Suppose A is the minimum label. So you choose to label the three pixels A, but that won't relabel the other B pixel. You still have to record that A==B, and will still have to sweep through to relabel any B's that remain. Furthermore, you might later find that A itself is equivalent to some other smaller label, and you'd have to relabel all these pixels later.

Related

Tonal value adjustment sliders, calculating values and positions

For processing raw photo data (16 bit linear) I'm programming a GUI interface for tonal value adjustment like in an old version of Photoshop, that I have:
A histogram is displayed, below it three sliders, one on the left for shadows, one on the left for bright tones, and one in the middle, I guess for the gamma. Above the histogram three fields, containing numerical values representing the slider positions.
When I move the left or the right slider, the one in the middle always moves to remain in the middle between the two, and the respective numerical value doesn't change.
When I move the slider in the middle the numerical value (gamma ?) changes, the values and positions of the left and right ones remain unchanged.
I guess the meaning of the values is: the left is the threshold for black, everything below becomes black in the result, for the right one the same happens for white: Everything above the threshold is set to white. The values in between are spread or shrunk to the space in between.
My questions are:
How do I calculate the new gamma value when I move the middle slider?
To which Image::Magick function should I "feed" the three values (lower and upper threshold, gamma value) to get the desired result? -level black_point{,white_point}{%}{,gamma} looks like it's the right one?
EDIT:
I thought the position of the middle slider in PS would somehow be related to the histogram above, but I have looked again and I think that's not the case. It just sets the gamma within a range of 9.9 to 0.1. So I found the answer to my first question.

Is there a known algorithm to find groups of adjacent pixels with similar color?

I'd like to know if this is a known algorithm with a name.
I've never done any image processing, but I'm picturing an image as a 2-d matrix of 3-d vectors (ignore transparency).
The only input parameter is distance. Every pixel is tested against its neighbors. If they are closer than the parameter, they join a group and their values are averaged. As groups grow by gaining new pixels all pixels get the average value of the group.
For your typical selfie the result might resemble quantizing or posterizing, but unlike quantizing or posterizing, there is no fixed count of output colors. If absolutely no pixels are close enough to their neighbors, the result is a 1:1 mapping of every pixel to its own group.
Is there a name for this?

How can I calculate center of mass after floodfill?

I have an image like this one
with 3 distinct regions. Using a breath first 4 neighbor queue, I have implemented a basic flood fill that distinguishes between the 3.
Now I need to find the center of mass of these regions with each pixel weighing one unit of weight.
Whats the best way of going about that?
The simplest way is to keep three arrays, sumx, sumy and count, each with one entry per label (3 in your case), and all initialized to 0. Then run through the image once, and for each labeled pixel add the x coordinate to the corresponding bin in sumx, the y coordinate to the corresponding bin in sumy, and 1 to the corresponding bin in count.
At the end, for each label l you can compute sumx[l]/count[l] and sumy[l]/count[l]. These are the unweighted centers of gravity (centroids).

Computer vision for a length ratio

Let's say I take a picture of two hammers side-by-side (although they may be aligned differently, but always one on the right and one on the left), wherein each might look like this, and I want to calculate the ratio of the lengths of the handles of the hammers.
For example, the output from an input image would be the length of the red part of the one on the left (its handle) divided by the length of the handle of the one on the right.
How would I go about doing this?
If you know the handle color it doesn't sound hard. Just select those pixels and take the longer side of a minimum oriented bounding box.
Here are a couple of hints:
Make sure that the bounding boxes of the hammers don't overlap. If you can guarantee this, try this approach:
Scale the image to width=10%, height=10px. Find the largest amount of pixels in background color near the middle of the image. That allows you to separate the two hammers into individual images. Multiply the positions by 10 to transform them back into coordinates of the original image.
Create two images (one for each hammer)
Crop the border
Scale the image to width = 10px, height = 10%. Count all reddish pixels (save the image and examine the pixel values for red and non-red parts to get an idea what to look for)

Given a set of points to define a shape, how can I contract this shape like Photoshop's Selection>Contract

I have a set of points to define a shape. These points are in order and essentially are my "selection".
I want to be able to contract this selection by an arbitrary amount to get a smaller version of my original shape.
In a basic example with a triangle, the points are simply moved along their normal which is defined by the points to the left and the right of the points in question.
Eventually all 3 points will meet and form one point but until that point they will make a smaller and smaller triangle.
For more complex shapes, when moving the individual points inward, they may pass through the outer edge of the shape resulting in weird artifacts. Obviously I'll need to cull these points and remove them from the array.
Any help in exactly how I can do that would be greatly appreciated.
Thanks!
This is just an idea but couldn't you find the center of mass of the object, create a vector from the center to each point, and move each point along this vector?
To find the center of mass would of course involve averaging each x and y coordinate. Getting a vector is as simple a subtracting the point in question with the center point. Normalizing and scaling are common vector operations that can be found with the Google.
EDIT
Another way to interpret what you're asking is you want to erode your collection of points. As in morphology erosion. This is typically applied to binary images but you can slightly modify the concept to work with a collection of points. Essentially, you need to write a function that, given a point, will return true (black) or false (white) depending on if that point is inside or outside the shape defined by your points. You'd have to look up how to do that for shapes that aren't always concave (it's harder but not impossible).
Now, obviously, every single one of your actual points will return false because they're all on the border (by definition). However, you now have a matrix of points around your point of interest that define where is "inside" and where is "outside". Average all of the "inside" points and move your actual point along the vector between itself and towards this average. You could play with different erosion kernels to see what works best.
You could even work with a kernel with floating point weights instead of either/or values which will affect your average calculation proportional to their weights. With this, you could approximate a circular kernel with a low number of points. Try the simpler method first.
Find the selection center (as suggested by colithium)
Map the selection points to the coordinate system with the selection center at (0,0). For example, if the selection center is at (150,150), and a given selection point is at (125,75), the mapped position of the point becomes (-25,-75).
Scale the mapped points (multiply X and Y by something in the range of 0.0..1.0)
Remap the points back to the original coordinate system
Only simple maths required, no need to muck about normalizing vectors.

Resources