前言
随着工业自动化、智能化的不断推进,机器视觉(2D/3D)在工业领域的应用和重要程度也同步激增(识别、定位、抓取、测量,缺陷检测等),而针对不同作业场景进行解决方案设计时,通常会借助PCL、OpenCV、Eigen等简单方便的开源算法库进行方案的快速验证和迭代以满足作业场景下的目标需求。
为了让对工业机器视觉方向感兴趣的同学能够少走一些弯路,故推出了此一系列简易入门教程示例,让初次使用者能够最简单直观地感受到当前所用算法模块的执行效果。
后续会逐步扩增与工业机器视觉相关的一些其它内容,如:
项目案例剖析、场景数据分析、基础算法模块、相机评测 等;
如有兴趣可加入群聊(若入群二维码被屏蔽,则可以通过Q群(1032861997)或评论、私信博主“群聊”,邀请入群),与同道同学及圈内同行一起交流讨论。
程序说明
提取图像物体边缘并生成最小包围框;
输出结果
代码示例
/*
* @File: approx_poly_dp.cpp
* @Brief: opencv course
* @Description: 展示提取图像物体边缘并生成包围框的效果
* @Version: 0.0.1
* @Author: MuYv
*/
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#define WINDOW_NAME1 "【原始图窗口】" //为窗口标题定义的宏
#define WINDOW_NAME2 "【效果图窗口】" //为窗口标题定义的宏
cv::Mat g_srcImage;
cv::Mat g_grayImage;
int g_nThresh = 50;//阈值
int g_nMaxThresh = 255;//阈值最大值
cv::RNG g_rng(12345);//随机数生成器
void on_ContoursChange(int, void* );
int main(int argc, char** argv)
{
if(argc != 2){
std::cout<<"Usage: exec img_file_path"<<std::endl;
return -1;
}
const std::string kImgFilePath = argv[1];
// 加载为 rgb 3通道彩色图数据
g_srcImage = cv::imread(kImgFilePath, cv::IMREAD_COLOR); // ../imgs/sea.jpg
// 得到原图的灰度图像并进行平滑
cv::cvtColor( g_srcImage, g_grayImage, cv::COLOR_BGR2GRAY );
cv::blur( g_grayImage, g_grayImage, cv::Size(3,3) );
// 创建原始图窗口并显示
cv::namedWindow( WINDOW_NAME1, cv::WINDOW_AUTOSIZE );
cv::imshow( WINDOW_NAME1, g_srcImage );
// 设置滚动条并调用一次回调函数
cv::createTrackbar(" 阈值:", WINDOW_NAME1, &g_nThresh,
g_nMaxThresh, on_ContoursChange );
on_ContoursChange( 0, 0 );
cv::waitKey(0);
return(0);
}
void on_ContoursChange(int, void* )
{
//定义一些参数
cv::Mat threshold_output;
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
// 使用Threshold检测边缘
cv::threshold( g_grayImage, threshold_output,
g_nThresh, 255, cv::THRESH_BINARY );
// 找出轮廓
cv::findContours( threshold_output, contours, hierarchy,
cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );
// 多边形逼近轮廓 + 获取矩形和圆形边界框
std::vector<std::vector<cv::Point> > contours_poly( contours.size() );
std::vector<cv::Rect> boundRect( contours.size() );
std::vector<cv::Point2f>center( contours.size() );
std::vector<float>radius( contours.size() );
// 一个循环,遍历所有部分,进行本程序最核心的操作
for( unsigned int i = 0; i < contours.size(); i++ )
{
//用指定精度逼近多边形曲线
cv::approxPolyDP( cv::Mat(contours[i]), contours_poly[i], 3, true );
//计算点集的最外面(up-right)矩形边界
boundRect[i] = cv::boundingRect( cv::Mat(contours_poly[i]) );
//对给定的 2D点集,寻找最小面积的包围圆形
cv::minEnclosingCircle( contours_poly[i], center[i], radius[i] );
}
// 绘制多边形轮廓 + 包围的矩形框 + 圆形框
cv::Mat drawing = cv::Mat::zeros( threshold_output.size(), CV_8UC3 );
for( int unsigned i = 0; i<contours.size( ); i++ )
{
//随机设置颜色
cv::Scalar color = cv::Scalar( g_rng.uniform(0, 255),
g_rng.uniform(0,255), g_rng.uniform(0,255) );
//绘制轮廓
cv::drawContours( drawing, contours_poly, i, color,
1, 8, std::vector<cv::Vec4i>(), 0, cv::Point() );
//绘制矩形
cv::rectangle(drawing,boundRect[i].tl(),boundRect[i].br(),color,2,8,0);
cv::circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 );//绘制圆
}
// 显示效果图窗口
cv::namedWindow( WINDOW_NAME2, cv::WINDOW_AUTOSIZE );
cv::imshow( WINDOW_NAME2, drawing );
}
注:部分测试所用图片数据来源于网络,如有侵权,请联系博主删除,谢谢。