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

这篇具有很好参考价值的文章主要介绍了机器学习与图像识别(二)—— 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文章来源地址https://www.toymoban.com/news/detail-842287.html

到了这里,关于机器学习与图像识别(二)—— OpenCV中aruco算法的坑的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包