ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

计算回形针方向

2021-06-07 13:03:11  阅读:293  来源: 互联网

标签:回形针 angle Point int double dev pEnd 计算 方向


摘要

本篇来用OpenCV实现Halcon中一个计算回形针方向的实例clip.hdev,并构建了计算角度函数和画箭头函数,得到的角度与halcon例程相差无多。


 原图如下:

 Halcon代码比较简单,这里也贴出来:

dev_update_window ('off')
read_image (Clip, 'clip')
get_image_size (Clip, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width / 2, Height / 2, 'black', WindowID)
dev_display (Clip)
set_display_font (WindowID, 14, 'mono', 'true', 'false')
disp_continue_message (WindowID, 'black', 'true')
stop ()
binary_threshold (Clip, Dark, 'max_separability', 'dark', UsedThreshold)
connection (Dark, Single)
select_shape (Single, Selected, 'area', 'and', 5000, 10000)
dev_set_draw ('fill')
dev_set_colored (12)
dev_display (Selected)
disp_continue_message (WindowID, 'black', 'true')
stop ()
dev_display (Clip)
dev_set_color ('green')
dev_display (Selected)
orientation_region (Selected, Phi)
area_center (Selected, Area, Row, Column)
dev_set_line_width (3)
dev_set_draw ('margin')
Length := 80
dev_set_color ('blue')
disp_arrow (WindowID, Row, Column, Row - Length * sin(Phi), Column + Length * cos(Phi), 4)
disp_message (WindowID, deg(Phi)$'3.1f' + ' deg', 'image', Row, Column - 100, 'black', 'false')
dev_update_window ('on')

  可以看到halcon的思路是:

    ① 读取图像 

    ② 二值化 

    ③ 根据面积剔除非回形针的region 

    ④ 计算每个region的方向和中心 

    ⑤ 画箭头,结果输出 

但是opencv中没有计算角度的函数和画箭头的函数,因此需要我们自己定义。

opecv实现:


 (一)构建角度计算函数


double calLineAngle(Point&ptStrat, Point&ptEnd)
{
    const double PI = 3.1415926;
    double angle = 0;
    if (ptStrat.x==ptEnd.x)
    {
        angle = 90;
    }
    else if (ptStrat.y==ptEnd.y)
    {
        angle = 0;
    }
    else
    {
        angle = atan((double)(ptEnd.y - ptStrat.y) / (ptEnd.x - ptStrat.x))*(180 / PI);
        if (angle<0)
        {
            angle = abs(angle);
        }
        else if (angle>0)
        {
            angle = 180 - angle;
        }
        if (ptEnd.y-ptStrat.y>0&&ptEnd.x-ptStrat.x)
        {
            angle = angle - 180;
        }
        
    }
    return angle;
}

反正切函数atan与atan2的区别

atan 和 atan2 都是求反正切函数,如:有两个点 point(x1,y1), 和 point(x2,y2);那么这两个点形成的斜率的角度计算方法分别是:

  • float angle = atan( (y2-y1)/(x2-x1) );
  • float angle = atan2( y2-y1, x2-x1 );

 atan 和 atan2 区别:

1:参数的填写方式不同;

2:atan2 的优点在于 如果 x2-x1等于0 依然可以计算,但是atan函数就会导致程序出错;


 (二)构建画箭头函数


void drawArrow(Mat&img, Point pStart, Point pEnd, int len, int alpha, Scalar color, int thickness, int lineType)
{
    const double PI = 3.1415926;
    Point arrow;
    //计算theat角
    double angel = atan2((double)(pStart.y - pEnd.y), (double)(pStart.x - pEnd.x));
    line(img, pStart, pEnd, color, thickness, lineType);
    //计算箭角边的另一端的端点位置(上面的还是下面的要看箭头的指向,即pStart和pEnd的位置)
    arrow.x = pEnd.x + len * cos(angel + PI * alpha / 180);
    arrow.y = pEnd.y + len * sin(angel + PI * alpha / 180);
    line(img, pEnd, arrow, color, thickness, lineType);
    arrow.x = pEnd.x + len * cos(angel - PI * alpha / 180);
    arrow.y = pEnd.y + len * sin(angel - PI * alpha / 180);
    line(img, pEnd, arrow, color, thickness, lineType);
}

 (三)主函数


int main(int argc, char** argv)
{
    double pointToLineDist(Point&pt, Point&lineStart, Point&lineEnd);
    double calLineAngle(Point&ptStrat, Point&ptEnd);
    void drawArrow(Mat&img, Point pStart, Point pEnd, int len, int alpha, Scalar color, int thickness, int lineType);


    Mat src = imread("D:/opencv练习图片/回形针方向.png");
    imshow("输入图像", src);
    Mat gray, binary;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    //阈值处理
    threshold(gray, binary, 150, 255, THRESH_BINARY_INV);
    imshow("二值化", binary);
    //寻找轮廓
    vector<vector<Point> > contours;
    findContours(binary, contours,  RETR_EXTERNAL, CHAIN_APPROX_NONE,Point());
    cout << contours.size() << endl;
    //轮廓分析,找到工件
    for (size_t i = 0; i < contours.size(); ++i)
    {
        //计算轮廓大小
        double area = contourArea(contours[i]);
        if (area < 12000)continue;
        double    max_dist = 0;
        Moments mm = moments(contours[i],false);
        Point ptCenter = Point(mm.m10 / mm.m00, mm.m01 / mm.m00);
        Point ptFarthest;
        for (int j = 0; j < contours[i].size(); j++)
        {
            double distance = sqrt(pow(contours[i][j].x - ptCenter.x, 2) + pow(contours[i][j].y - ptCenter.y, 2));
            if (distance>max_dist)
            {
                ptFarthest = Point(contours[i][j].x, contours[i][j].y);
                max_dist = distance;
            }
        }
        cout << max_dist << endl;
        drawContours(src, contours, i, Scalar(0, 0, 255), 5, 8);
        drawArrow(src, ptCenter, ptFarthest, 25, 30, Scalar(255,0,255), 3, 8);
        double angle = calLineAngle(ptCenter, ptFarthest);
        cout << angle << endl;
        char strAngle[20];
        sprintf_s(strAngle, "%0.1fdegree", angle);
        putText(src, strAngle, ptCenter, FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0, 255, 255), 2, 8);
    }
    imshow("结果", src);
    waitKey(0);
    return 0;
}

 

 

  参考于:OpenCV与AI深度学习

标签:回形针,angle,Point,int,double,dev,pEnd,计算,方向
来源: https://www.cnblogs.com/xyf327/p/14858419.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有