13

Is there a way to prevent auto-focus from focusing, using any of the "standard" libraries, such as OpenCV, EmGU, DirectShow, etc?

I want auto-focus to find the optimal focus, then during video capture, prevent auto-focus from auto-focusing.

I know I can manually set the value, but that defeats the purpose of using auto-focus, and I have yet to find a way to obtain the optimal focus value as determined by the auto-focus.

jps
  • 11,454
  • 12
  • 42
  • 55
  • It may be possible to use the **camera**'s autofocus to find the optimal focus and then lock that. Are you still interested in this approach? (I saw you accepted Oliort's answer.) Do you use a USB webcam? – Ulrich Stern May 07 '19 at 16:54
  • That is the whole issue. How to lock the optimal focus. There is no way of finding the optimal manual focus value that was obtained by the auto-focus. – RickInWestPalmBeach May 07 '19 at 16:58
  • There appears to be a way for my webcam. Posting this shortly. – Ulrich Stern May 07 '19 at 17:24
  • 1
    @UlrichStern in some cases cameras native auto-focus may not be suitable. I don't know if that is the case for RickInWestPalmBeach. I updated my answer and covered the case when the object we want to focus at is small / has complex shape / not-centered position (which will make native auto-focus to fail most probably). – Oliort May 09 '19 at 13:15
  • 1
    @Oliort, I think both our solutions are good. I generally dislike reimplementing functionality that is already there (especially if it appears to work well), but I agree that the UVC-based solution has disadvantages, too (portability, etc.). – Ulrich Stern May 09 '19 at 16:45

3 Answers3

6

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.

Ulrich Stern
  • 8,926
  • 4
  • 46
  • 68
  • Confirmed for Logitech Brio too. You can also use `-c focus_absolute=` to set the focus level after setting auto focus off like above (`-c focus_auto=0`). It's a pity viewing angle cannot be controlled though. – matanster Oct 03 '20 at 15:57
  • Additional utilities from the same project that can help you diagnose things are listed [here](https://linuxtv.org/wiki/index.php/V4l-utils), for example there is `v4l2-compliance` – matanster Oct 03 '20 at 16:01
  • There seems to be an equivalent library for API consumption, libv4l, which you can install as a linux package. Projects such as https://pypi.org/project/PyV4L2Camera/ use it and give the package name per linux flavor. Documentation for this library is inlined in its header file: `libv4l2.h` which you get after installing the package per your linux flavor, however it's a lower level interface that what the utilities provides, so best to follow the code of the command-line utilities I guess, for developing against that library. – matanster Oct 03 '20 at 16:16
4

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.

Oliort
  • 1,360
  • 11
  • 27
0

Native Windows API for controlling focus is IAMCameraControl interface with CameraControl_Focus property. It is available via DirectShow and most likely (I did not check but I expect it to be there as is) via Media Foundation as well. Libraries mentioned in the first paragraph of the question work on top of these APIs.

For example, Logitech HD Webcam C615 camera (just grabbed the first random one with focusing) exposes such capabilities with regard to focus:

  • CameraControl_Focus: 51, flags CameraControl_Flags_Auto | CameraControl_Flags_Manual, 0..255, step 17, default 51, cap flags CameraControl_Flags_Auto | CameraControl_Flags_Manual

This suggest that the range is 0..255 with increments of 17, that is the camera has automatic focusing and manual focusing from the range of 16 settings. The API is designed in the way that one could potentially auto-focus, then read the automatically determined setting and then switch to manual with this setting locking the focus (everything via IAMCameraControl interface).

I am afraid, however that, a lot of cameras are not implementing this accurate enough relying basically just on built-in auto-focus capability. First of all, you can't read the status whether auto or manual refocusing is in progress, then reading current setting in auto mode might return wrong value (e.g. last used during manual focusing). Even though there is a standard defined way to work with focus, it remains something not actively used and which might be not working well enough. Perhaps you have interest in specific model and the camera implements this well.

On focus identification through image analysis you already have pointers in neighboring answers.

Roman R.
  • 64,446
  • 5
  • 83
  • 139