Reputation: 747
I have a camera pointed at a monitor displaying a line of white pixels. I get an array of byte values back from the camera. The area of the camera's view is larger than the space taken up by the monitor. I need to find out where on the camera image the white monitor pixels appear. See the sample image below.
I need to improve my algorithm so that it is more robust in varying lighting conditions. Specifically, I need to improve the step where I determine the value threshold for what are considered potential white pixels. After determining what are likely my white pixels, I find the largest neighborhood to determine my final white values.
I also tried counting the N pixels with the highest values and considering the lowest value of the N pixels as white. This worked fairly well in some conditions, but it stopped working when the room got slightly darker. I can tweak N to work in any lighting condition, but I would prefer not to have to provide any parameters manually. I am experimenting with using percentiles now, but it is running quite slow since the data set is very large.
Here's one of the methods that works decently, but the parameters have to be tweaked in different lighting conditions.
std::multiset<uint8_t> maxPixelValues;
for(unsigned i = 0; i < width; ++i)
{
for(unsigned j = 0; j <height; ++j)
{
uint8_t pixelValue = buffer[j * width + i];
if(maxPixelValues.size() < topPixelCount)
{
maxPixelValues.insert(pixelValue);
}
else
{
auto minimumValuePosition = maxPixelValues.begin();
if(pixelValue > *minimumValuePosition)
{
maxPixelValues.erase(minimumValuePosition);
maxPixelValues.insert(pixelValue);
}
}
}
}
return *maxPixelValues.begin();
Upvotes: 1
Views: 333
Reputation: 3709
First you might want to threshold at one standard deviation above the mean to get rid of the darker parts of the screen. Then you can take advantage of the fact that the line is quite thin compared to some of the brighter area in the background and also far away from other bright areas thanks to the edge of the screen.
Pseudocode:
mask=threshold(img, mean(img)+stdev(img))
toignore=dilate(mask,3,3)
toignore=erode(toignore,4,4)
toignore=dilate(toignoe,3,3)
mask=mask &! toignore
There are a few stray pixels left, but you can probably do a hough transform at this point.
Upvotes: 3
Reputation: 9275
You can use Hough transform to find lines on an image: http://en.wikipedia.org/wiki/Hough_transform
Here is the openCV api: http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html
Upvotes: 0