How to lock autofocus

You can detect when the image is focused during calibration phase (when you are finding the optimal focus) and save that configuration (focus distance). Then set the focus to the saved value and disable auto-focus before capturing phase. To find the optimal focus distance you can start with the most close (macro) focus distance and gradualy raise it to maximum, measuring how focused the image is.

This SO question has an answer that describes how to measure if the image is focused or not. You can use OpenCV Laplacian() (Emgu.CV) to achieve that.

The key is that in-focus image has much more strong gradients and sharp features. So what I suggest is to apply a Gaussian Laplace filter and then look at the distribution of pixel values of the result. The in-focus one has much more high values (because the image has more sharp gradients).

Another interesting way to determine best focus is described in this article. The technique is used in the NASA Curiosity Mars Rover. The idea is to JPEG-compress the frames and use the size of jpegs as the measure of focus.

The autofocus command instructs the camera to move to a specified starting motor count position and collect an image, move a specified number of steps and collect another image, and keep doing so until reaching a commanded total number of images, each separated by a specified motor count increment. Each of these images is JPEG compressed (Joint Photographic Experts Group; see CCITT (1993)) with the same compression quality factor applied. The file size of each compressed image is a measure of scene detail, which is in turn a function of focus (an in-focus image shows more detail than a blurry, out of focus view of the same scene).

OpenCV imencode() (Emgu.CV) can be used to compress the image in JPEG.

If you want to focus on some specific stable object or area and you are able to calculate / recognize its fixed position, you should process only that area to determine best focus. In the first approach you can apply Laplacian to cropped rectangular area or even use not rectangular mask for result "focus value" calculation if you know shape of the object. The same is for the second approach - compress only the region of interest you want to focus at. If you want it to process not rectangular areas and know the shape of the region, first set all pixels which do not cover the region you focus at to same color. It will make the algorithm not to take account of regions you do not need to be focused.


For USB webcams that are UVC-compatible (as most are), there is a reasonable chance one can use the camera's autofocus and then lock it. To figure out whether the camera allows this via UVC, on Linux one can use v4l2-ctl, which is in package v4l-utils. v4l2-ctl -l lists all available controls, v4l2-ctl -c sets the value for a control, and v4l2-ctl -C gets the value.

For example, the following commands did the trick for a Microsoft LifeCam Cinema on an Ubuntu 16.04 box that had a simple Python OpenCV program running to display the current frame:

> v4l2-ctl -d 0 -c focus_auto=1
> v4l2-ctl -d 0 -C focus_absolute
focus_absolute: 12

After moving the object closer to the camera, the focus changed, and I got a different value for focus_absolute: (So UVC gives access to what what value the autofocus picked.)

> v4l2-ctl -d 0 -C focus_absolute
focus_absolute: 17

I then changed to manual focus and this locked the value the autofocus had picked:

> v4l2-ctl -d 0 -c focus_auto=0
> v4l2-ctl -d 0 -C focus_absolute
focus_absolute: 17

So for the LifeCam Cinema, the only thing the code would need to do is change the focus_auto control initially to auto (1) and then to manual once the focus is to be locked.

From Python, I typically run v4l2-ctl simply by using subprocess.check_output(). I recall seeing Windows libraries for UVC, but never played with them.