分类 OpenCV_图像_视觉_算法 下的文章

作为一位从业多年的机器视觉算法工程师。以下是我对Opencv、Halcon、VisionPro和VisionMaster这四个软件的个人综合评价,包括它们的优缺点以及适用场景。

Opencv

优点:

开源免费: Opencv是一个开源的计算机视觉库,对于预算有限的项目和个人开发者来说,这是一个巨大的优势。

社区支持: 有一个庞大的用户社区,提供了大量的文档、教程和代码示例,帮助新手快速上手和解决问题。

跨平台: 支持Windows、Linux和MacOS等多种操作系统,使得在不同平台上的迁移和部署变得容易。

丰富的功能: 提供了丰富的算法和功能,包括图像处理、特征提取、目标跟踪等,几乎涵盖了计算机视觉的所有基础领域。

缺点:

性能问题: 在某些情况下,Opencv的性能可能不如专业的商业软件,尤其是在处理大规模数据或者实时应用时。

算法库的局限性: 对于一些高级的视觉任务,Opencv可能没有现成的解决方案,需要用户自己开发或者寻找第三方库。

适用场景:

Opencv适合于教育、研究和原型开发,以及那些需要快速开发和部署计算机视觉应用的场合。

Halcon

优点:

高性能: Halcon是为工业级应用设计的,它的算法优化得非常好,适合处理大量数据和实时应用。

丰富的算法库: 提供了广泛的图像处理和分析功能,包括3D视觉、深度学习、形状匹配等。

易于集成: Halcon提供了易于使用的API和支持多种编程语言的接口,可以方便地集成到各种工业自动化系统中。

缺点:

成本: Halcon是一款昂贵的商业软件,可能不适合预算有限的项目。

学习曲线: 对于初学者来说,Halcon的学习曲线比较陡峭,需要投入较多的时间来掌握其复杂的功能。

适用场景:

Halcon适用于对性能要求极高的工业视觉系统,如自动化检测、质量控制、机器人引导等。

VisionPro

优点:

用户友好的界面: VisionPro拥有直观的图形用户界面,可以通过拖放的方式快速设计视觉应用。

强大的工具集: 提供了一系列强大的视觉工具,如图像增强、目标定位、缺陷检测等。

良好的硬件支持: VisionPro支持广泛的工业相机和视觉硬件,使得系统集成相对容易。

缺点:

成本: 与Halcon相似,VisionPro也是一款商业软件,价格不菲。

定制性: 尽管VisionPro很强大,但对于需要高度定制的视觉应用,可能需要额外的开发工作。

适用场景:

VisionPro适合于需要快速部署的工业视觉检测系统,尤其是在使用Cognex相机或者其他支持的硬件时。

VisionMaster(海康威视)

优点:

定制性强: VisionMaster提供了灵活的软件框架和开发工具,允许开发者根据需求进行高度定制。

成本效益: 相对于其他商业软件,VisionMaster可能提供更具竞争力的定价,适合中小企业。

技术支持: 通常提供良好的技术支持服务,帮助用户解决开发和部署过程中的问题。

缺点:

知名度和普及度: VisionMaster可能没有像Opencv、Halcon和VisionPro那样广泛的用户基础和社区支持。

资源和文档: 相较于其他成熟的软件,VisionMaster可能在资源和文档方面稍显不足。

适用场景:

VisionMaster适用于需要定制化解决方案的机器视觉应用,尤其是在预算相对有限的情况下。

总结

在选择机器视觉软件时,需要根据项目的具体需求、预算和开发资源来做出决策。Opencv适合于研究和原型开发,Halcon和VisionPro则更适合高性能的工业应用。VisionMaster提供了一定程度的定制性,可能适合预算有限的中小企业。每种软件都有其独特的优势和局限性,理解这些差异对于构建成功的机器视觉系统至关重要。

机器视觉——视觉方案设计总结

引言

机器视觉工程师不仅仅是编写图像程序和界面的,最重点的是要提供一整套视觉解决方案,来保证你这套算法能够正常运行,需要考虑的事情比较多,望大家共勉。


当我们做视觉验证方案的时候,需要先拿到客户给的样品,然后制定方案。需要注意一下几点:

  • 视野大小:首先根据产品的大小,和客户的视觉检测要求,我们要确定镜头的视野大小,一般情况下视野都要比我们需要检测的区域大1/3,拿尺子量出来,记录下初步的视野大小,单位是MM
  • 工作距离:确定一下我们的镜头离产品到底有多少距离,有些是客户提供,有些是工程设计提供一些大体的要求,我们再做决定大体的一个工作距离,单位:mm
  • 镜头焦距:根据视野大小和工作距离,我们可以求一下镜头的焦距,具体公式如下: 焦距f = WD工作距离 × 靶面尺寸( H or V) / FOV 视野大小( H or V)
  • 相机的选择
  1. 黑白相机:这个是大部分案子的选择
  2. 彩色相机:除了一些需要进行颜色检测的案子外,彩色相机的选择可以作为对黑白相机的一个补充,例如:有些产品,黑白相机拍出来的图像对比度比较差,我们进行图像处理的时候非常不方便,这个时候就需要用到彩色相机了,彩色相机拍摄的图像,转化成黑白图像,在转化的过程中,我们可以进行转化参数RGB的调整,调出我们需要的黑白图像。

一,相机选择

面阵相机和线扫相机:

面阵相机是我们大部分应用的相机,一般都是选择全快门的。
所谓的线阵相机,比较适合拍摄移动物体检测,玻璃面板检测瑕疵用的多数是线阵相机,印刷行业也用的比价多。

💙💙💙相机的选型主要选择多少万像素分辨率的相机,选择公式如下:  

首先要确定客户要求的精度,一般情况下都是 精度 = 0.02mm ,除非客户有更高精度的要求。

我们选型要用的精度一般都是在客户的基础是在放大2倍或者3倍,即,精度 = 客户精度/2 。那么我们的相机的分辨率就是:相机分辨率 = FOV 视野大小H/精度再就是至于其他的参数验证的过程中再进一步计算,一般的视觉这些就用了。

智能相机: 

漏下了智能相机了,所谓的智能相机就是带有操作系统的小型计算机,里面配有专门的图像算法库,单独的OS,可以独立运行。智能相机目前和机器人配合用的比较多,有钱的公司可以用,或者特殊环境下。

二,镜头的选择

  1. 一般的广角镜头:一般情况下都是选择500万镜头,如果有特殊要求,可以在选择高精度低畸变的镜头  
  2. 远心镜头: 3C行业用的比较多。检测视野比较小,精度要求较高的时候选择远心镜头,如果有特殊尺寸,可以选择定制圆心镜头。因为远心镜头成像的范围和镜头口径大小有很大关联。
  3. 线扫相机的镜头是专门的线扫相机镜头
  4. 其他的镜头,随着视觉行业的发展,产品的种类也越来越多。

三,光源的选择

对于光源来说,它的作用就是保证相机可以拍摄到我们做图像处理可以用的图像为原则,做打光测试的时候,多多试验。

环形光、条形光、点光源、同轴光、碗状光源(又叫穹顶光源)等等。。光源还是有很多颜色的,白色、蓝色、红色、紫外线等等

以上的这些主要的目的就是要获取我们做图像处理需要的原材料——图像,再就是我们设计的视觉照明系统一定要保证稳定,可以稳定的获取相同规格的图像

四,图像软件的选择

只介绍行业内用的最多的视觉库

  • 一般是Visionpro最简单,容易上手和调试,修改也最方便
  • Halcon功能最强大
  • OpenCV,从这里很多公司自己调试封装算法库
  • LabView配合NI图像处理软件

从事视觉行业一定要知道行业内的老大和老二:

基恩士绝对的老大,东西贵的一逼,精度高,速度快.再就是老二,康耐视,Cognex,Visionpro就是他家的。

最后补充下:

还有2D镭射激光测量仪,3D激光成像仪,这是作为高精度测量要求的(基恩士的是最好的吧,15万以上吧。)

还有双目相机组成的3D成像系统,还有结构光3D相机,等等吧。种类比较多

最后,保存图像,写图像程序,查看图像处理的结果是否达到客户的哟求,最后写方案文档。客户最终确定之后,写视觉系统界面,场内初步调试,出厂,客户现场调试。到客户现场后,我们的程序经常要修改,包括图像程序,客户可能要添加各种功能和要求什么时候,设备正常运转了,我们的视觉系统稳定了,什么时候你就可以回公司了

在有些图像处理场景,需要对某块不规则的图像区域进行过滤,此时可以先用cv::fillPoly()函数预先生成相应的mask,然后再将待过滤的图像与

mask进行与操作。


注意: cv::fillPoly()中出入的多边形点集的顺序不是随机的,而是按照多边形封闭的原则,多边形的点是按照顺时针方向或逆时针方向依次存储.


/*----------------------------------------------------------------------------------------
**      注意: cv::fillPloy 第二个参数点顺序不能是随意的,而是要按照图形封闭的原则,按顺时针
** 或逆时针顺序排列, 比如下面的梯形:
**
**              top left<1> ---------> top right<2>
**             /                                   \
**            /                                     \
**           /                                       \
**     bottom left<4>   <------------------     bottom right<3>
**
** ---------------------------------------------------------------------------------------*/
void    OpenCV_Generate_ROI_Mask(const cv::Point &tl, const cv::Point &tr,\
                                 const cv::Point &bl, const cv::Point &br,\
                                 int w, int h, cv::Mat &mask_img)
{
    mask_img = cv::Mat::zeros(h, w, CV_8UC1);
    std::vector<cv::Point>  pts;
    pts.push_back(tl);  // 1
    pts.push_back(tr);  // 2
    pts.push_back(br);  // 3
    pts.push_back(bl);  // 4
    cv::fillPoly(mask_img, pts, 255); // Gray mask, for BGR: cv::fillPoly(mask_img, pts, cv::Scalar(0,0,255))
    //cv::imwrite("Mask.png", mask_img);
    return;
}







cv::bitwise_and(image, roi_mask, image);  //待过滤的图像与mask进行与操作.












import cv2
import os
import sys

# Function to extract frames from a video until reaching the desired frame count
def extract_frames(video_file):
    cap = cv2.VideoCapture(video_file)

    frame_rate = 2  # Desired frame rate (1 frame every 0.5 seconds)
    frame_count = 0

    # Get the video file's name without extension
    video_name = os.path.splitext(os.path.basename(video_file))[0]

    # Create an output folder with a name corresponding to the video
    output_directory = f"{video_name}_frames"
    os.makedirs(output_directory, exist_ok=True)

    while True:
        ret, frame = cap.read()

        if not ret:
            break

        frame_count += 1

        # Only extract frames at the desired frame rate
        if frame_count % int(cap.get(5) / frame_rate) == 0:
            output_file = f"{output_directory}/frame_{frame_count}.png"
            cv2.imwrite(output_file, frame)
            print(f"Frame {frame_count} has been extracted and saved as {output_file}")
        if frame_count >= 30:
            break

    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    if len(sys.argv)<2:
        print("Usage:\n  < mp4 file name >")
        sys.exit()
    if 2== len(sys.argv):
        files = sys.argv[1:]
        video_file = files[0]
        sys.exit(extract_frames(video_file))
    else:

        sys.exit()