机器学习与图像识别(二)—— OpenCV中aruco算法的坑

进入正题之前

OpenCV是一个优秀的开源视觉处理软件框架,也是计算机视觉学习道路上必须掌握的一套工具,奈何其版本兼容性上实在是一言难尽。本文主要介绍不同版本下使用aruco算法遇到的坑与排雷方法。如果你也刚好遇到类似的问题并且靠着本文的处理方式解决掉你的麻烦,不妨搜一搜VX公众号“24K纯学渣”,可能会有更多的惊喜噢。本文将持续更新。。。

PS:如果本文找不到你遇到的问题,可以去官方文档搜,传送门:https://docs.opencv.org/

版本说明

opencv 3.4.2.17 是最后一版支持免费使用sift等模板匹配算法的版本,之后的版本由于版权问题去掉了一些可能会被收费的模块。

aruco算法从4.7.0开始进入到opencv-python主库

Python中使用aruco

如果只需要主要模块 pip install opencv-python
如果需要更全的模块 pip install opencv-contrib-python
如果资源较少,不需要任何GUI功能 pip install opencv-python-headless
如果资源较少,不需要任何GUI功能,包含contrib模块 pip install opencv-contrib-python-headless
因此一般来说都会选择安装opencv-contrib-python不要同时安装opencv-python和opencv-contrib-python。
关于安装包的问题解决完以后,新版本的安装包在原来的代码上会连续报如下错误,对应新版本修改即可。
————————————————
版权声明:本文为CSDN博主「童鸢」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41837701/article/details/129256430

安装

# for Linux-like OS
pip3 install opencv-python==x.x.x.x

# for Windows
pip install opencv-python==x.x.x.x

aruco算法

只安装了opencv-python

import cv2 # opencv-python==4.8.1.78

img = cv2.imread("./in_imgs/4x4_15.png", 0)
cv2.imshow("img", img)

ad = cv2.aruco.ArucoDetector()
corners, ids, rejected = ad.detectMarkers(img)
cv2.waitKey()
cv2.destroyAllWindows()

只安装 opencv-contrib-python==3.4.2.17,环境是CentOS 7.9 server版本

import cv2 # opencv-python==3.4.2.17

img = cv2.imread("./in_imgs/4x4_15.jpg", cv2.IMREAD_COLOR)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# cv2.imshow("img", img) # 由于没有GUI,无法调用imshow函数

arucoDict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_4X4_50)
arucoParams = cv2.aruco.DetectorParameters_create()
corners, ids, rejected = cv2.aruco.detectMarkers(img_gray, arucoDict, parameters=arucoParams)

print(corners, ids, rejected)

img = cv2.aruco.drawDetectedMarkers(img, corners, ids, [0,255,0])
cv2.imwrite("./out_imgs/detected_aruco.jpg", img)

(1)AttributeError: module ‘cv2.aruco’ has no attribute ‘Dictionary_get’
cv2.aruco.Dictionary_get()函数会加载cv2.aruco.DICT_nXn_250包含250个标记的字典,其中每个标记都是n×n位二进制模式。
在最新的版本中,这个函数的API改为了 cv2.aruco.getPredefinedDictionary
(2)AttributeError: module ‘cv2.aruco’ has no attribute ‘DetectorParameters_create’
cv2.aruco.DetectorParameters_create这个函数的作用是使用默认值初始化检测器参数改为了cv2.aruco.DetectorParameters
————————————————
版权声明:本文为CSDN博主「童鸢」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41837701/article/details/129256430

(3)centos7和ubuntu18.04分别解决cv2缺少共享库( libSM.so.6)的解决方法:

yum install libSM-1.2.2-2.el7.x86_64 --setopt=protected_multilib=false 
yum install libXrender-0.9.10-1.el7.x86_64 --setopt=protected_multilib=false
yum install libXext-1.3.3-3.el7.x86_64 --setopt=protected_multilib=false

C++ 中使用aruco算法

安装 VS+opencv

  • 先安装Visual Studio,如果已经安装请跳过!
  • 官网下载opencv-windows.exe
  • 执行open-windows.exe,记住安装的路径
  • 添加opencv的环境变量到Path中:C:\your\local\env\path\for \opencv\build\x64\vc16
  • 将C:\your\local\env\path\for \opencv\build\x64\vc16\bin下的opencv_videoio_ffmpeg480_64.dll、opencv_world480.dll、opencv_world480d.dll 复制到 C:\Windows\System32\下。
  • 新建一个d_opencv_env.props 和 r_opencv_env.props文本文件,分别复制下面的内容到对应的属性表文件中。注意路径!!!

属性表(Debug):
注意: C:\your\local\env\path\for 换成你自己的安装路径。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ImportGroup Label="PropertySheets" />
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <IncludePath>C:\your\local\env\path\for\opencv\build\include;C:\your\local\env\path\for\opencv\build\include\opencv2;$(IncludePath)</IncludePath>
    <LibraryPath>C:\your\local\env\path\for\opencv\build\x64\vc16\lib;$(LibraryPath)</LibraryPath>
  </PropertyGroup>
  <ItemDefinitionGroup>
    <Link>
      <AdditionalDependencies>C:\your\local\env\path\for\opencv\build\x64\vc16\lib\opencv_world480d.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup />
</Project>

属性表(Release):
注意: C:\your\local\env\path\for 换成你自己的安装路径。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ImportGroup Label="PropertySheets" />
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <IncludePath>C:\your\local\env\path\for\opencv\build\include;C:\your\local\env\path\for\opencv\build\include\opencv2;$(IncludePath)</IncludePath>
    <LibraryPath>C:\your\local\env\path\for\opencv\build\x64\vc16\lib;$(LibraryPath)</LibraryPath>
  </PropertyGroup>
  <ItemDefinitionGroup>
    <Link>

<AdditionalDependencies>C:\your\local\env\path\for\opencv\build\x64\vc16\lib\opencv_world480.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup />
</Project>

验证 Aruco算法,opencv==4.8.0

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/objdetect/aruco_detector.hpp>


int main(int argc, char const *argv[])
{
	//std::cout << "先生成一个aruco marker" << std::endl;
	
	//std::cout << "保存生成的aruco marker" << std::endl;

	std::cout << "1. 读取aruco marker" << std::endl;
    cv::Mat img_color = cv::imread("./in_imgs/4x4_15.jpg", cv::IMREAD_COLOR);
	//cv::Mat img = cv::imread("./in_imgs/4x4_15.jpg", cv::IMREAD_COLOR);
    cv::Mat img;
    cv::cvtColor(img_color, img, cv::COLOR_BGR2GRAY);

    //宽度
    std::cout << "宽度: " << img.cols << std::endl;
    //高度
    std::cout << "高度: " << img.rows << std::endl;
    //通道数
    std::cout << "通道数: " << img.channels() << std::endl;

    cv::imshow("aruco_15", img);

    auto dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_4X4_50);
    std::vector<std::vector<cv::Point2f>>corners, rejectedImgPoints;
    std::vector<int> ids;
    auto parameters = cv::aruco::DetectorParameters();
    //cv::aruco::detectMarkers(img, dictionary, corners, ids, parameters, rejectedImgPoints);
    cv::aruco::ArucoDetector ad = cv::aruco::ArucoDetector();
    ad.detectMarkers(img, corners, ids);
    cv::aruco::drawDetectedMarkers(img_color, corners, ids, cv::Scalar(0, 255, 0));
    
    if (ids.size() > 0)
    {
        std::cout << ids[0] << std::endl;
    }

    cv::imshow("drawed", img_color);
    cv::waitKey();
	return 0;
}

Python + C++一起使用aruco算法

具体来说就是用C++写识别的接口,然后编译成dll/so,然后在python中调用即可,需要用到python中的内置ctypes模块,该模块提供了cdll接口,能调用.dll文件,不过需要注意的是,该模块调用的dll中只能包含C语言特性,C++特性无法使用,比如函数重载、namespace等等。

VS创建一个dll的项目,教程:
VS2022 C/C++ DLL封装
编写头文件:

#pragma once

#include <iostream>
#include <opencv2/opencv.hpp>

//函数的声明, 测试使用的函数,只依赖C++
extern "C" __declspec(dllexport) void test_dll();
extern "C" __declspec(dllexport) int my_detect_aruco_markers(int rows, int cols, unsigned char* img,
	int aruco_type, int target_ID, int ret_mode);

编写对应的源文件:

#include "opencv_aruco.h"

void test_dll()
{
	std::cout << "这是测试DLL的函数!" << std::endl;
	return;
}


int  my_detect_aruco_markers(int rows, int cols, unsigned char *img_src,
	int aruco_type, int target_ID = 0, int ret_mode = 0)
{
	cv::Mat img = cv::Mat(rows, cols, CV_8UC3, img_src);
	cv::Mat img_gray;

	if (img.channels() > 1)
	{
		cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
	}

	auto dictionary = cv::aruco::getPredefinedDictionary(aruco_type);
	std::vector<std::vector<cv::Point2f>>corners, rejectedImgPoints;
	std::vector<int> ids;
	auto parameters = cv::aruco::DetectorParameters();
	//cv::aruco::detectMarkers(img, dictionary, corners, ids, parameters, rejectedImgPoints);
	cv::aruco::ArucoDetector ad = cv::aruco::ArucoDetector();
	ad.detectMarkers(img_gray, corners, ids);

	if (ret_mode == 1)
	{
		cv::aruco::drawDetectedMarkers(img, corners, ids, cv::Scalar(0, 0, 255));
		cv::imwrite("./dll_write.jpg", img);
		return 0;
	}
	else if (ret_mode == 2)
	{
		if (ids.size() > 0)
		{
			for (int i = 0; i < ids.size(); ++i)
			{
				if (ids[i] == target_ID)
				{
					return 0;
				}
			}
		}
		return -1;
	}

	return 0;
}

然后,点击“生成–> 生成xxx dll”,即可在对应的release/debug目录下生成dll文件,记录该dll文件所在路径,编写python脚本如下:

import ctypes
import cv2
img = cv2.imread(r"./in_imgs/4x4_15.jpg")
rows, cols = img.shape[0], img.shape[1]

my_dll = ctypes.cdll.LoadLibrary(r"./dll/aruco_dll.dll")

my_dll.my_detect_aruco_markers(rows, cols, 
    img.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte)), 
    0, 15, 1)

这里需要注意的是,通过ctypes调用dll文件中的接口时,需要指定传参参数类型,尤其是类似cv::Mat这种c语言里面没有定义的变量类型,本案例处理的方法是,传图像的rows与cols,然后传一个uint8_t类型的指针用来存放该数据,然后在C++代码中将其转为cv::Mat类型的变量即可,参考下面一些文章:

Python使用ctypes调用动态库dll/so,关于opencv图片Mat对应的数据uchar*

windows下python调用含有opencv Mat类型的dll文件的方法

c++ 里的cv:mat 怎么返回传递给python

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
机器学习水果识别是一种利用机器学习算法和图像处理技术对水果进行自动识别的方法。其,使用PythonOpenCV库实现物体特征提取是一种常见的实现方式。 OpenCV是一个强大的开源计算机视觉库,提供了许多用于图像处理和分析的函数和工具。它可以辅助我们实现水果识别所需要的特征提取步骤。 首先,我们需要准备水果图像数据集。这些图像可以是不同种类的水果,每个水果都有多个不同视角的图像。接下来,我们使用OpenCV的函数加载和处理这些图像。 在特征提取,我们可以使用很多不同的技术。其,最常用的方法是使用图像的颜色和纹理特征。在处理图像时,我们可以使用OpenCV的函数计算这些特征。 例如,我们可以使用OpenCV的函数提取图像的颜色直方图。这可以帮助我们了解图像不同颜色的比例和分布情况。在水果识别,不同水果的颜色特征往往是不同的。 此外,我们还可以使用OpenCV的纹理特征提取方法,比如局部值模式(Local Binary Patterns)。这可以帮助我们分析图像的纹理信息,如图像的细节和纹理变化。这些纹理特征在识别不同类型的水果时也是有用的。 最后,我们可以使用机器学习算法,如支持向量机(SVM)或卷积神经网络(CNN),来训练一个分类模型。这个模型可以根据提取的特征来判断输入图像是否为某种水果。 总之,使用PythonOpenCV库实现水果识别的物体特征提取是一种非常有效的方法。通过提取图像的颜色和纹理特征,并使用机器学习算法进行分类,我们可以实现一个准确和高效的水果识别系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值