0
$\begingroup$

I'm new to the world of image processing, and I need some hints to analyze an image.

I have a sensor which is made up of a high resolution CMOS camera sensor and there's a mask with a micrometric hole on it.

A light shines through the mask and the pinhole creates a circular projection on the camera's CMOS. Since the projection affects only 10-20 pixels out of the 8MP of the sensor, what would be a smart way to process the image the fastest way possible? I'm now using Matlab's native code but I want to code it myself.

The sensor is self-powered, so CPU processing is an issue.

Someone suggested wavelet analysis, I was wondering if that's really my best shot.

What do you think?

$\endgroup$
  • $\begingroup$ Can you please clarify what are you trying to do exactly? Do you want to estimate the Point Spread Function (PSF) of the camera? Is the camera imaging something else and you want to obtain a pattern of interference? $\endgroup$ – A_A Jul 30 '16 at 8:31
2
$\begingroup$

I'm going to go ahead and assume currently using Matlab implies you're on a laptop or PC-alike device with a modern x86 CPU; optimal/efficient/power-saving DSP depends on the hardware you're on, but if we have the features of a fully fledged PC platform, it becomes pretty easy :)

I think this is the classical case where a linear search doesn't hurt.

Assume your pictures come in a in a row-major format, i.e. each pixel lies in memory next to its left and right neighbours, and the top and bottom neighbours are one row width of pixels away.

Since memory bandwidth is the limiting factor for simple operations on data, it's always important to minimize the times you fetch new memory – things that are in the CPU registers can directly be used for calculations, whereas things that still are in RAM easily take a couple hundred multiplications worth of CPU time to just get loaded, which is why there is an intermediate RAM cache in your CPU, which your processor can use efficiently – unless you jump wildly through memory as you process, because then it newer knows what it should keep in cache and what to throw out to make space for new stuff.

So, row-major greyscale.

You go to the first row in your picture, and search for the brightest pixel; you keep a variable storing both the value (necessary for searching) and the index of that pixel (column). At the same time, you keep a sum of pixels. At the end of the row, you store that sum and the index of the brightest pixel.

Move on to the next row, and so on.

At some point, you might want to terminate; either you've run out of rows, or your algorithm has produced enough high row sums, and isn't producing them anymore, so you've probably found your circular spot.

With the brightest pixel column indices and knowing in which rows that happened, you have your region of interest in linear time, without thrashing the CPU cache.

If this isn't fast enough for you, the nice thing about the operations you've been doing (sum, comparison with value) is that modern x86 CPUs have instructions that let you these operations with up to 16 operands at once (depending on the data type you're using underneath), so this might be a good time to look into that. I'd recommend not writing SIMD intrinsics from hand for a start, but looking into VolkVOLK (Vector Optimized Library of Kernels) which should have the routines you need, at least for floating point, already.

Yet another thing: this can be highly scaled on multiple CPUs. If you've got four CPU cores, the first could do the upper fourth of the image, the second the next fourth and so on. Same goes for doing this with OpenCL on your graphics card – but do remember that the whole data marshalling in and out of graphic cards and GPU drivers might eat its performance children rather easily.


So, with your Region Of Interest detected, you can do multiple things. I'd just go ahead and copy the smaller subimage of which I'm sure contains the whole spot into a new, compact image, and probably store it for later verification (at least as long I'm still developing); then I'd go and let one of the classical circle-finding approaches loose on the image: Typically, the circular Hough transform will do just fine. Notice that you could have done that directly with the original image, but you'd have lost a lot of time spent on transforming things that definitely don't contain circles. The OpenCV has circular Hough built-in.


A bit of development advice: don't prematurely optimize! Get your raw ROI detection working with whatever programming language you prefer (since we're talking about most efficient implementations here, this is pretty likely to be C/C++, but needn't be! A functional programming language might make it a lot easier for the compiler and runtime to parallelize things, though it will be harder (if possible at all) to later on sneak SIMD intrinsics into the code.). You'll probably notice that pretty much everything beats the speed of the Matlab interpreter by orders of magnitude, whereas the natively implemented low-level algorithms within Matlab are highly optimized (you pretty much will have a hard time beating the speed of Matlab's FFT implementation – which is FFTw, by the way, or it's matrix/vector operations, which are BLAS/LAPACK, and so on). But practical algorithms not only do elementary operations but also have program flow defined in matlab M-code, and that, performance-wise and from the point of elegance, is stuck somewhere in the early 80's, at times. So you'd be surprised how much you often can win purely by practically writing the same program in Python, using numpy, scipy, pyOpenCV, without touching low-level coding at all.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.