Baumer工业相机堡盟工业相机如何通过BGAPISDK使用AutoFocus自动对焦功能(C++)

Baumer工业相机

Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。

Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩展性等特点。

Baumer工业相机由于其性能和质量的优越和稳定,常用于高速同步采集领域,通常使用各种图像算法来提高其捕获的图像的质量。

Baumer工业相机BGAPISDK和AutoFocus功能的技术背景

Baumer工业相机的BGAPI SDK是Baumer公司开发的针对其相机产品系列的一套软件开发工具包。该SDK提供了一组API,使开发人员可以编写专业应用程序,从而控制、捕获、处理和显示Baumer相机的图像和数据。BGAPI SDK支持多种编程语言,包括C++、C#、Visual Basic、LabVIEW、Matlab等,并提供了大量示例代码和文档,以帮助用户轻松上手,快速完成应用程序的开发。

BGAPI SDK提供了丰富的功能,可以控制Baumer相机的所有参数,包括曝光时间、增益、白平衡、触发模式等,以及支持各种数据格式,例如Raw、BMP、JPG等,同时还提供了实时显示、数据采集、图像处理等功能,为开发人员提供了高度定制化的解决方案。此外,BGAPI SDK还支持多相机系统的开发,并可支持各种计算机操作系统,如Windows、Linux、Mac OS等。

工业相机的AutoFocus功能是指该相机具备自动对焦功能,可以通过相机自身或外部设备(如光电传感器、激光测距仪等)对物体进行快速、精准的自动对焦。

自动对焦功能可以大大提高相机的拍摄效率和准确性,特别是在工业生产、机器视觉、智能制造等领域中,可以快速、准确地识别物体、测量尺寸和形状等参数,从而实现自动化生产和质量控制。

在选择工业相机时,需要根据具体应用场景考虑是否需要AutoFocus功能,并根据需求选择相应的对焦方式和适合的镜头。

本文介绍的使用BGAPI SDK进行使用AutoFocus功能。

Baumer工业相机通过BGAPISDK使用AutoFocus功能

下面介绍在C++里Baumer工业相机如何通过BGAPISDK使用AutoFocus功能方式

1.引用合适的类文件

代码如下(示例):


#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <set>
#include <vector>
#include <algorithm>
#include <string>
#include "bgapi2_genicam/bgapi2_genicam.hpp"




2.通过BGAPISDK使用AutoFocus自动对焦功能

Baumer工业相机设置自动对焦AutoFucus功能核心代码如下所示:


SystemList 
Open a System 
Get the InterfaceList and fill it Open an Interface 
Get the DeviceList and fill it 
Open a Device 

typedef struct _Result {
    
    
    int64_t sharp_value;
    int64_t lens;
    int64_t method_value;
} Result;

std::map<int64_t, Result> result_map;

//---------------------------------------------------------------------------------------------------------------------
// This example uses a Software Trigger to get images from the camera. This method will trigger regularly using 
// a separate thread to trigger and calculate in parallel.
void SoftwareTriggerThread(BGAPI2::Device* device, int64_t time_delay) {
    
    
    std::this_thread::sleep_for(std::chrono::milliseconds(time_delay));
    device->GetRemoteNode("TriggerSoftware")->Execute();
}

void ExampleAutoFocus(BGAPI2::Device* device) {
    
    

    std::thread trigger_thread;

    const uint64_t lens_delay = 70;      // A delay required for settling the liquid lens 
    const int64_t  focus_threshold = 85;  // Threshold in percent for detection of a peak!

    BGAPI2::ImageProcessor* image_processor = new BGAPI2::ImageProcessor();
    device->GetRemoteNode("AcquisitionStop")->Execute();  // to make sure that camera stopped

    BGAPI2::Node* lens_focus = device->GetRemoteNode("OpticFeatureValue");
    BGAPI2::String pixel_format = device->GetRemoteNode("PixelFormat")->GetString();
    const int image_width = static_cast<int>(device->GetRemoteNode("Width")->GetInt());
    const int image_height = static_cast<int>(device->GetRemoteNode("Height")->GetInt());

    ROI roi = {
    
    200, 200, 400, 300};   // We only use a region of the image to set the focus

    int64_t focus_start_step = 1000;  // The step size to jump for next measurement
    int64_t focus_step = focus_start_step;
    int64_t lens_focus_max = std::min(static_cast<bo_int64>(40000), lens_focus->GetIntMax());
    int64_t lens_focus_min = std::max(static_cast<bo_int64>(10000), lens_focus->GetIntMin());
    int64_t focus_value = lens_focus->GetInt();  // the start value for the algorithm

    // Detect and open the data stream
    BGAPI2::DataStreamList *datastreamList = device->GetDataStreams();
    datastreamList->Refresh();
    BGAPI2::DataStream *datastream = datastreamList->begin()->second;
    datastream->Open();

    // Add 4 buffers to the data stream
    BGAPI2::BufferList *bufferList = datastream->GetBufferList();
    for (int i = 0; i < 4; i++) {
    
    
        BGAPI2::Buffer* buffer = new BGAPI2::Buffer();
        bufferList->Add(buffer);
        buffer->QueueBuffer();
    }
    BGAPI2::Buffer* buffer_filled = nullptr;

    //------------------------------------------------------------------------------------
    // A high gain value is bad for a good auto focus (regarding noise)!
    device->GetRemoteNode(SFNC_GAINSELECTOR)->SetString(SFNC_GAINSELECTORVALUE_ALL);
    device->GetRemoteNode(SFNC_GAIN)->SetValue("1.0");

    datastream->StartAcquisitionContinuous();

    // use camera auto function to obtain well balanced images
    AutoBrightnessWhiteBalance(device, datastream, roi);
    //------------------------------------------------------------------------------------
    device->GetRemoteNode("TriggerSource")->SetString("Software");
    device->GetRemoteNode("TriggerMode")->SetString("On");
    device->GetRemoteNode("AcquisitionStart")->Execute();
    device->GetRemoteNode("TriggerSoftware")->Execute();

    int64_t sharp_min = 1L << 30;
    int64_t sharp_max = 0;
    int64_t sharp_maxno = 0;
    const std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now();

    bool is_min_focus = false;
    bool is_max_focus = false;
    bool is_finished = false;

    for (int i = 0; !is_finished; i++) {
    
    
        int64_t read_focus_value = lens_focus->GetInt();
        buffer_filled = datastream->GetFilledBuffer(1000);
        if (buffer_filled == nullptr) {
    
    
            std::cout << "Error: Buffer Timeout after 1000 ms" << std::endl;
            device->GetRemoteNode("TriggerSoftware")->Execute();
        } else if (buffer_filled->GetIsIncomplete() == true) {
    
    
            std::cout << "Error: Image is incomplete" << std::endl;
            buffer_filled->QueueBuffer();
        } else {
    
      
            
            // get a correct picture, check the calculated value and calculate the next step
            //=======================================================
            if (lens_focus) {
    
    
                int64_t next_focus = focus_value + focus_step;
                if (next_focus > lens_focus_max)
                    is_max_focus = true;
                if (next_focus < lens_focus_min)
                    is_min_focus = true;
                if (is_min_focus && is_max_focus) {
    
    
                    is_finished = true; break;  // reached both limits!
                }

                if (!is_min_focus && !is_max_focus) {
    
    
                    if (focus_step > 0) {
    
    
                        focus_step = -focus_step - focus_start_step;
                        if (next_focus + focus_step < lens_focus_min) {
    
    
                            is_min_focus = true;
                            focus_step = +focus_start_step;
                        }
                    } else {
    
    
                        focus_step = -focus_step + focus_start_step;
                        if (next_focus + focus_step > lens_focus_max) {
    
    
                            is_max_focus = true;
                            focus_step = -focus_start_step;
                        }
                    }
                } else {
    
    
                    if (!is_min_focus) {
    
    
                        focus_step = -focus_start_step;
                    } else if (!is_max_focus) {
    
    
                        focus_step = +focus_start_step;
                    }
                    next_focus = focus_value + focus_step;
                }

                focus_value = next_focus;
                if (focus_value > lens_focus_max) {
    
    
                    is_finished = true;
                }
                //=======================================================

                if (!is_finished) {
    
      // -> next setting and image

                    lens_focus->SetInt(focus_value);
                    trigger_thread = std::thread(&SoftwareTriggerThread, device, lens_delay);
                }

                void* buffer_pointer = buffer_filled->GetMemPtr();
                uint64_t buffer_size = buffer_filled->GetSizeFilled();
                BGAPI2::Image* image = image_processor->CreateImage(image_width, image_height,
                    pixel_format, buffer_pointer, buffer_size);
                CheckAndFixRoi(&roi, image_width, image_height);

#if USE_OPENCV
                // Display the image
                if (pixel_format == "Mono8") {
    
    
                    ShowImage(buffer_pointer, image_width, image_height, CV_8UC1, &roi);
                } else {
    
    
                    // Convert to BGR8
                    const size_t size = static_cast<size_t>(image->GetTransformBufferLength("BGR8"));
                    char* mem_buffer = new char[size];
                    if (mem_buffer) {
    
    
                        image_processor->TransformImageToBuffer(image, "BGR8", mem_buffer, size);
                        ShowImage(mem_buffer, image_width, image_height, CV_8UC3, &roi);
                        delete[] mem_buffer;
                    }
                }
#endif
                // Convert to Mono8 for measurement sharpness
                const size_t size = static_cast<size_t>(image->GetTransformBufferLength("Mono8"));
                uint8_t* mem_buffer = new uint8_t[size];
                if (mem_buffer) {
    
    
                    image_processor->TransformImageToBuffer(image, "Mono8", mem_buffer, size);
                    int64_t sharpness = 0;
                    //-----------------------------------------------------------------
                    // The algorithm for measurement of sharp:
                    // Here you can use: prewitt, sobel, scharr - or you use an own algorithm like
                    // open_cv laplacian, DFT (FFT), canny or something else
                    // we use Sobel Sharpening! see HelperFuntions -> sobel matrix
                    sharpness = CrossCalculateMono(mem_buffer, image_width, image_height,
                        sobel_x, sobel_y, roi);
                    //-----------------------------------------------------------------
                    result_map[read_focus_value].lens = read_focus_value;
                    result_map[read_focus_value].method_value = sharpness;
                    if (sharpness < sharp_min) {
    
    
                        sharp_min = sharpness;
                    }
                    if (sharpness > sharp_max) {
    
    
                        sharp_max = sharpness;
                        sharp_maxno = read_focus_value;
                    }
                    if (sharpness < (focus_threshold * sharp_max) / 100) {
    
    
                        if (read_focus_value < sharp_maxno) {
    
    
                            is_min_focus = true;
                        } else {
    
    
                            is_max_focus = true;
                        }
                    }
                    delete[] mem_buffer;
                }
                buffer_filled->QueueBuffer();
            }
        }
        if (trigger_thread.joinable())
            trigger_thread.join();
    }

    int64_t meanvalue = 0;
    int64_t meancount = 0;
    int64_t auto_focus_value = -1;
    int64_t new_focus = -1;
    int64_t max_sharpness = sharp_max;
    lens_focus_min = lens_focus_max = -1;
    for (auto result : result_map) {
    
    
        if (lens_focus_min < 0)
            lens_focus_min = result.first;
        if (result.second.method_value * 100 > focus_threshold * max_sharpness) {
    
    
            lens_focus_max = result.first;
            meanvalue +=
                result.second.method_value * (result.first - lens_focus_min);
            meancount++;
        } else if (lens_focus_max < 0)
            lens_focus_min = result.first;
    }
    int64_t outside_min = -1;
    int64_t outside_max = -1;
    for (auto result : result_map) {
    
    
        if (result.second.method_value * 100 > focus_threshold * max_sharpness) {
    
    
            outside_max = result.first;
        } else if (outside_max < 0) {
    
    
            outside_min = result.first;
        } else {
    
    
            outside_max = result.first;
            break;
        }
    }
    if (outside_min > 0 && outside_max > 0 &&
        (result_map.find(outside_min + 1000) != result_map.end()) &&
        (result_map.find(outside_max - 1000) != result_map.end())) {
    
    
        int64_t threshold = (focus_threshold * max_sharpness) / 100;
        int64_t min = 1000 * (threshold - result_map[outside_min].method_value) /
            (result_map[outside_min + 1000].method_value - result_map[outside_min].method_value);
        outside_min += min;
        int64_t max = 1000 * (threshold - result_map[outside_min].method_value) /
            (result_map[outside_max - 1000].method_value - result_map[outside_min].method_value);
        outside_max -= max;

        new_focus = (outside_min + outside_max) / 2;
    }

    if (new_focus < 0) {
    
    
        new_focus = sharp_maxno;
    }
    if (lens_focus && (new_focus > lens_focus_min) && (new_focus < lens_focus_max)) {
    
    
        auto_focus_value = new_focus;
        lens_focus->SetInt(auto_focus_value); // set the new calculated value to the camera!

#if USE_OPENCV
        // read an image and show it (if you use OpenCV)
        SoftwareTriggerThread(device, lens_delay);
        buffer_filled = datastream->GetFilledBuffer(1000);
        if (buffer_filled) {
    
    
            BGAPI2::Image* image = image_processor->CreateImage(image_width, image_height,
                buffer_filled->GetPixelFormat(), buffer_filled->GetMemPtr(), 
                buffer_filled->GetSizeFilled());

            const size_t size = static_cast<size_t>(image->GetTransformBufferLength("BGR8"));
            char* mem_buffer = new char[size];
            
            if (mem_buffer) {
    
    
                image_processor->TransformImageToBuffer(image, "BGR8", mem_buffer, size);
                ShowImage(mem_buffer, image_width, image_height, CV_8UC3, nullptr);
            }
            buffer_filled->QueueBuffer();
        } else {
    
    
            std::cout << "don't get last buffer!" << std::endl;
        }
#endif

        std::chrono::duration<double, std::milli> overall_delay =
            std::chrono::system_clock::now() - start_time;
        std::cout << "AutoFocus finished after " << overall_delay.count() << "ms and " <<
            result_map.size() << " images, focus value = " << auto_focus_value << "!" << std::endl;
    } else {
    
    
        std::cout << "The camera couldn't focused correctly!" << std::endl;
    }
    // clean up camera and buffers
    device->GetRemoteNode("AcquisitionAbort")->Execute();
    device->GetRemoteNode("AcquisitionStop")->Execute();
    device->GetRemoteNode("TriggerMode")->SetString("Off");
    datastream->StopAcquisition();
    bufferList->DiscardAllBuffers();
    while (bufferList->size() > 0) {
    
    
        BGAPI2::Buffer* buffer = bufferList->begin()->second;
        bufferList->RevokeBuffer(buffer);
        delete buffer;
    }
    datastream->Close();

    if (image_processor != nullptr) {
    
    
        delete image_processor;
        image_processor = nullptr;
    }

}



3.通过BGAPISDK运行测试AutoFocus自动对焦功能


SystemList 
Open a System 
Get the InterfaceList and fill it Open an Interface 
Get the DeviceList and fill it 
Open a Device 

int main(int numArgs, char *args[]) 
{
    
    
    
    int returncode = 0;
    int64_t camfound = 0;

    std::cout << "BGAPI2 Example 503 - AutoFocus"  << std::endl;

#ifndef USE_OPENCV   // OpenCV
    // this part is use if no matching OpenCV found in CMake!
    std::cout << "Without OpenCV buffer images are not shown on screen and not saved to files!" << std::endl;
    std::cout << "Availability of OpenCV is checked while CMake creates this project." << std::endl;
    std::cout << "Please install OpenCV (version 2.3 or later) or set 'OpenCV_DIR' to the" << std::endl;
    std::cout << "correct path in the CMakeList.txt script or as a variable in your environment" << std::endl;
    std::cout << "and run CMake again. " << std::endl;
    std::cout << "######################################" << std::endl << std::endl;
#endif  // USE_OPENCV

    try {
    
    
        // First search for a camera which supports the liquid lens
        // We use the feature "OpticFeatureValue" to check if the camera supports the liquid lens
        
        // Get the list of systems and loop through
        BGAPI2::SystemList *system_list = BGAPI2::SystemList::GetInstance();
        system_list->Refresh();

        for (auto system_pair : *system_list) {
    
    
            auto system = system_pair->second;  // gige, usb3, ..
            system->Open();

            // Get the list of interfaces on the system and loop through
            auto interface_list = system->GetInterfaces();
            interface_list->Refresh(100);
            for (auto interface_pair : *interface_list) {
    
    
                auto interface = interface_pair->second;
                interface->Open();
                auto device_list = interface->GetDevices();
                device_list->Refresh(100);

                // Get the list of devices and loop though them to find a camera supporting a liquid lens
                for (auto device_pair: *device_list) {
    
    
                    BGAPI2::Device* device = device_pair->second;
                    device->Open();
                    
                    std::stringstream camera_name;
                    camera_name << device->GetModel() << "(SN = " << device->GetSerialNumber() << ")";
                    if (device->GetRemoteNodeList()->GetNodePresent("OpticFeatureValue")) {
    
    
                        if (!device->GetRemoteNode("OpticFeatureValue")->IsWriteable()) {
    
    
                            continue;
                        }
                    } else {
    
    
                        continue;
                    }
                    std::cout << "Camera found!" << std::endl;
#ifdef _DEBUG
                    // Switch off the heartbeat in debug mode, otherwise the camera might disconnect during debug!
                    if (device->GetRemoteNodeList()->GetNodePresent("DeviceLinkHeartbeatMode"))
                        device->GetRemoteNode("DeviceLinkHeartbeatMode")->SetString("Off");
#endif

                    // no try to focus the camera
                    ExampleAutoFocus(device);

#ifdef _DEBUG
                    // Switch the heartbeat back on
                    if (device->GetRemoteNodeList()->GetNodePresent("DeviceLinkHeartbeatMode"))
                        device->GetRemoteNode("DeviceLinkHeartbeatMode")->SetString("On");
#endif
                    // close the camera
                    device->Close();
                    
                    camfound = 1;
                    break;  // if one camera found!
                }
                interface->Close();
                if (camfound)
                    break;  // if one camera found!
            }
            system->Close();
            if (camfound)
                break;  // if one camera found!
        }
        if (camfound == 0) {
    
    
            std::cout << "No camera found on any system and any interface!" << std::endl;
        }
    }
    catch (BGAPI2::Exceptions::IException& ex) {
    
    
        returncode = (returncode == 0) ? 1 : returncode;
        std::cout << "Error in function: " << ex.GetFunctionName() << std::endl << "Error description: "
            << ex.GetErrorDescription() << std::endl << std::endl;
    }
    BGAPI2::SystemList::ReleaseInstance();


#ifdef USE_OPENCV   // OpenCV
    // Wait a delay
    cv::waitKey(10000);  // show a little while of 5 seconds the focused image
    cv::destroyAllWindows();
#else
    for (int i = 0; i < 5; i++) {
    
      // a little while of 5 seconds...
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
#endif
    return returncode;
}
    


Baumer工业相机使用AutoFocus自动对焦功能的优势

工业相机使用AutoFocus自动对焦功能有以下优势:

提高工作效率:自动对焦功能可以快速、准确地识别并对焦目标物体,避免了手动调节对焦焦距带来的时间浪费。因此,使用自动对焦功能可以提高生产效率,节省时间和人力成本。

提高测量精度:自动对焦功能可以根据不同的拍摄距离和物体大小,自动调整对焦焦距,保证图像清晰度和测量精度。

适应不同场景:自动对焦功能适应范围广泛,可以应用于工业生产、机器视觉、智能制造等多个领域中,对于不同大小、不同形状的目标物体均能有效识别并对焦,具有很高的通用性。

减少使用难度:相对于手动调节对焦焦距,自动对焦功能更易于操作和使用,减少了对操作人员技术水平的要求,也降低了需要培训的成本。

总之,自动对焦功能是现代工业相机的重要功能之一,对于提高工作效率、测量精度和操作便利性都有很大的帮助。

Baumer工业相机使用AutoFocus自动对焦功能的行业应用

工业相机使用AutoFocus自动对焦功能在许多行业具有广泛的应用价值,以下是一些常见的行业应用:

机器视觉检测:自动对焦功能可以帮助机器视觉系统自动识别各种零件,进行尺寸测量、外观检测和定位等。这在制造业、电子行业、汽车行业等领域具有重要价值。

材料科学与无损检测:借助自动对焦功能,工业相机可用于对材料表面进行精确的缺陷检测(如裂纹、气孔等),提高检测的准确性和速度,用于金属制品、塑料制品等行业。

医疗健康:利用自动对焦功能,工业相机可以提供精确的成像数据,辅助进行病理分析、影像诊断等医学应用。例如,在显微镜成像、内窥镜成像等医学设备中进行快速对焦。

生物科技:自动对焦功能可用于生物制品样品检测、显微成像、基因芯片成像等领域,实现高速、高精度的图像处理与分析。

半导体工业:自动对焦可用于芯片制程的检测与质量控制,检查晶圆、封装等组件的缺陷。减少缺陷率,监控生产质量。

能源行业:工业相机的自动对焦功能可以应用于太阳能电池板、核电站等能源设施的检测与维护,保障设备的正常运行与安全。

安防监控:自动对焦功能可用于监控摄像头的调整与控制,确保拍摄到清晰的监控图像,提高安防系统的效果。

总之,在各行业应用中,工业相机使用AutoFocus自动对焦功能可以提高图像处理速度和准确性,实现对目标物体的快速捕捉和检测,提高生产效率和质量。

猜你喜欢

转载自blog.csdn.net/xianzuzhicai/article/details/131266094