1. Home
  2. Docs
  3. Jetson Cameras
  4. Native Jetson Cameras – IMX219/IMX477
  5. IMX219 – Motorized Focus Camera

IMX219 – Motorized Focus Camera

Introduction

The autofocus camera is an advanced IMX219 camera module for Jetson Nano/Xavier NX board. It helps to focus the object in close range from 5cm~30cm, within this range the standard fixed focus camera can not get sharp focus and the image looks burry. All the focus procedure is controlled by the software without manually adjust the lens barrel.​

To learn more about autofocus with Raspberry Pi camera modules, we recommend you read Raspberry Pi Camera Autofocus: The Complete Guide.

Models in this Series

There are four cameras in this series. The main differences between them are IR sensitivity and whether the camera board is included. They are the same in terms of software operation.

B0190
B0182
B0181
B0189
SKUModelField of ViewIR Sensitivity
B0190IMX219-drop-in-replacement77.6°D x 65°H x 51°VNoIR(IR sensitive)
B0182IMX219-drop-in-replacement77.6°D x 65°H x 51°VVisible Light
B0181IMX219 Autofocus Module77.6°D x 65°H x 51°VVisible Light
B0189IMX219 Autofocus Module77.6°D x 65°H x 51°VNoIR(IR sensitive)
Too short camera cable?

You may need Arducam 30cm Sensor Extension Cable which extends the small camera module with a much longer distance and fit into the space-constrained environment.

Common Specs

General Specifications

Sensor ModelIMX219
Shutter TypeRolling Shutter
Active Pixels3280 (H) × 2464 (V)
Resolution8MP
Image Sensor FormatType 1/4″
Pixel Size1.12μm×1.12μm
CSI-2 Data Output2-lane mode
Data FormatRaw Bayer 10bit
IMX219 block diagram
IMX219 Block Diagram

Quick Start Guide

Hardware Setup​​​​​

  1. Locate the camera connector (CSI). It’s on the side of the carrier board, opposite to the GPIO pins.
  1. Pull up on the plastic edges of the camera port. Do it gently to avoid pulling it off.
plastic edges pulled up jetson nano camera connector csi
  1. Push in the camera ribbon. Make sure the contacts are facing the heatsinks. Do not bend the flex cable, and make sure it’s firmly inserted into the bottom of the connector.
white camera ribbon cable contacts
Ribbon Cable Contacts – 15pin-15pin
white cable silver contacts facing heatsinks
Silver Contacts facing inside to the heatsinks
white cable silver ribbon cable inserted into the bottom of the connector
Ribbon cable fully inserted to the bottom of the CSI connector
  1. Push the plastic connector down. Do it while holding the flex cable until the connector is back in place.

Software Setup​​

Preparation

  • Start up your Raspberry Pi.
  • Go to the main menu and open the Raspberry Pi Configuration tool.Raspberry Pi Configuration Tool
  • Select the Interfaces tab and ensure that the camera is enabled:Camera enabled
  • Reboot your Raspberry Pi.

First Use

1.Download Arducam’s Jetson Nano repository
git clone https://github.com/ArduCAM/Nvidia_Jetson.git
2.Enter the folder with the autofocus demo
cd Nvidia_Jetson/IMX219_AutoFocus
3.Run the demo​​​​​

This example python code is modified from JetsonHacks sample code in order to work with Arducam Autofocus IMX219 camera module.

sudo python Autofocus.py
# MIT License
# Copyright (c) 2019 JetsonHacks
# See license
# Using a CSI camera (such as the Raspberry Pi Version 2) connected to a 
# NVIDIA Jetson Nano Developer Kit using OpenCV
# Drivers for the camera and OpenCV are included in the base image

import cv2
import numpy as py
import os

def focusing(val):
	value = (val << 4) & 0x3ff0
	data1 = (value >> 8) & 0x3f
	data2 = value & 0xf0
	os.system("i2cset -y 6 0x0c %d %d" % (data1,data2))
	
def sobel(img):
	img_gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
	img_sobel = cv2.Sobel(img_gray,cv2.CV_16U,1,1)
	return cv2.mean(img_sobel)[0]

def laplacian(img):
	img_gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
	img_sobel = cv2.Laplacian(img_gray,cv2.CV_16U)
	return cv2.mean(img_sobel)[0]


# gstreamer_pipeline returns a GStreamer pipeline for capturing from the CSI camera
# Defaults to 1280x720 @ 60fps 
# Flip the image by setting the flip_method (most common values: 0 and 2)
# display_width and display_height determine the size of the window on the screen

def gstreamer_pipeline (capture_width=1280, capture_height=720, display_width=1280, display_height=720, framerate=60, flip_method=0) :   
    return ('nvarguscamerasrc ! ' 
    'video/x-raw(memory:NVMM), '
    'width=(int)%d, height=(int)%d, '
    'format=(string)NV12, framerate=(fraction)%d/1 ! '
    'nvvidconv flip-method=%d ! '
    'video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! '
    'videoconvert ! '
    'video/x-raw, format=(string)BGR ! appsink'  % (capture_width,capture_height,framerate,flip_method,display_width,display_height))

def show_camera():
    max_index = 10
    max_value = 0.0
    last_value = 0.0
    dec_count = 0
    focal_distance = 10
    focus_finished = False
    # To flip the image, modify the flip_method parameter (0 and 2 are the most common)
    print gstreamer_pipeline(flip_method=0)
    cap = cv2.VideoCapture(gstreamer_pipeline(flip_method=0), cv2.CAP_GSTREAMER)
    if cap.isOpened():
        window_handle = cv2.namedWindow('CSI Camera', cv2.WINDOW_AUTOSIZE)
        # Window 
        while cv2.getWindowProperty('CSI Camera',0) >= 0:
            ret_val, img = cap.read()
            cv2.imshow('CSI Camera',img)
            
            if dec_count < 6 and focal_distance < 1000:
                #Adjust focus
                focusing(focal_distance)
                #Take image and calculate image clarity
                val = laplacian(img)
                #Find the maximum image clarity
                if val > max_value:
                    max_index = focal_distance
                    max_value = val
                    
                #If the image clarity starts to decrease
                if val < last_value:
                    dec_count += 1
                else:
                    dec_count = 0
                #Image clarity is reduced by six consecutive frames
                if dec_count < 6:
                    last_value = val
                    #Increase the focal distance
                    focal_distance += 10

            elif not focus_finished:
                #Adjust focus to the best
                focusing(max_index)
                focus_finished = True
            # This also acts as 
            keyCode = cv2.waitKey(16) & 0xff
            # Stop the program on the ESC key
            if keyCode == 27:
                break
            elif keyCode == 10:
                max_index = 10
                max_value = 0.0
                last_value = 0.0
                dec_count = 0
                focal_distance = 10
                focus_finished = False
        cap.release()
        cv2.destroyAllWindows()
    else:
        print 'Unable to open camera'


if __name__ == '__main__':
    show_camera()

Was this article helpful to you? Yes No