OpenCV实现halcon的select_shape函数

6 篇文章 0 订阅
enum SelectShapeType
{
    SELECT_AREA,			//选中区域面积
    SELECT_RECTANGULARITY,	//选中区域矩形度
    SELECT_WIDTH,			//选中区域宽度(平行于坐标轴)
    SELECT_HEIGHT,			//选中区域高度(平行于坐标轴)
    SELECT_ROW,				//选中区域中心行索引
    SELECT_COLUMN,			//选中区域中心列索引
    SELECT_RECT2_LEN1,		//选中区域最小外接矩形的一半长度
    SELECT_RECT2_LEN2,		//选中区域最小外接矩形的一半宽度
    SELECT_RECT2_PHI,   	//选中区域最小外接矩形的方向
    SELECT_ELLIPSE_RA,      //选中区域外接椭圆的长半轴
    SELECT_ELLIPSE_RB,      //选中区域外接椭圆的短半轴
    SELECT_ELLIPSE_PHI      //选中区域外接椭圆的方向
};

enum SelectOperation
{
    SELECT_AND,		//与
    SELECT_OR		//或
};

//功能:借助形状特征选择区域
//参数:
//  src:输入图像
//  dst:输出图像
//  types:要检查的形状特征
//  operation:各个要素的链接类型(与、或)
//  mins:下限值
//  maxs:上限值
//返回值:无
int select_shape(Mat src, Mat &dst,
                 vector<SelectShapeType> types,
                 SelectOperation operation,
                 vector<double> mins,
                 vector<double> maxs)
{
    if (!(types.size() == mins.size() && mins.size() == maxs.size()))
        return 0;

    int num = types.size();
    dst = Mat(src.size(), CV_8UC1, Scalar(0));

    vector<vector<Point>> contours;
    findContours(src, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    int cnum = contours.size();

    vector<vector<Point>> selectContours;

    int thread_num = std::max(1, std::min(getNumThreads(), getNumberOfCPUs()));
    int cur_td_n = std::min(thread_num, cnum);

    parallel_for_(Range(0, cnum), [&](const Range& boundaries) {
        for (int i = boundaries.start; i < boundaries.end; i++)
        {
            bool isAnd = true;
            bool isOr = false;
            for (int j = 0; j < num; j++)
            {
                double mind = mins[j];
                double maxd = maxs[j];
                if (mind > maxd)
                {
                    mind = maxs[j];
                    maxd = mins[j];
                }

                if (types[j] == SELECT_AREA)
                {
                    if(contourArea(contours[i])<mind)
                    {
                        isAnd &= false;
                        isOr |= false;
                        continue;
                    }

                    Mat temp = Mat(src.size(), CV_8UC1, Scalar(0));
                    vector<vector<Point>> pconver;
                    pconver.push_back(contours[i]);
                    drawContours(temp, pconver, -1, Scalar(255), CV_FILLED);
                    bitwise_and(src, temp, temp);
                    int area = cv::countNonZero(temp);
                    if (area >= mind && area <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_RECTANGULARITY)
                {
                    Mat temp = Mat(src.size(), CV_8UC1, Scalar(0));
                    vector<vector<Point>> pconver;
                    pconver.push_back(contours[i]);
                    drawContours(temp, pconver, -1, Scalar(255), CV_FILLED);
                    bitwise_and(src, temp, temp);
                    int area = cv::countNonZero(temp);
                    RotatedRect rect = minAreaRect(contours[i]);
                    if(0==rect.size.area())
                    {
                        continue;
                    }
                    double rectangularity = area / rect.size.area();
                    if (rectangularity >= mind && rectangularity <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_WIDTH)
                {
                    Rect rect = boundingRect(contours[i]);
                    if (rect.width >= mind && rect.width <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_HEIGHT)
                {
                    Rect rect = boundingRect(contours[i]);
                    if (rect.height >= mind && rect.height <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_ROW)
                {
                    Mat temp = Mat(src.size(), CV_8UC1, Scalar(0));
                    vector<vector<Point>> pconver;
                    pconver.push_back(contours[i]);
                    drawContours(temp, pconver, -1, Scalar(255), CV_FILLED);
                    bitwise_and(src, temp, temp);
                    int area;
                    Point2f center;
                    area_center(temp, area, center);
                    if (center.y >= mind && center.y <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_COLUMN)
                {
                    Mat temp = Mat(src.size(), CV_8UC1, Scalar(0));
                    vector<vector<Point>> pconver;
                    pconver.push_back(contours[i]);
                    drawContours(temp, pconver, -1, Scalar(255), CV_FILLED);
                    bitwise_and(src, temp, temp);
                    int area;
                    Point2f center;
                    area_center(temp, area, center);
                    if (center.x >= mind && center.x <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_RECT2_LEN1)
                {
                    RotatedRect rect = minAreaRect(contours[i]);
                    double len = rect.size.width;
                    if (rect.size.width < rect.size.height)
                        len = rect.size.height;
                    if (len/2 >= mind && len/2 <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_RECT2_LEN2)
                {
                    RotatedRect rect = minAreaRect(contours[i]);
                    double len = rect.size.height;
                    if (rect.size.width < rect.size.height)
                        len = rect.size.width;
                    if (len/2 >= mind && len/2 <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_RECT2_PHI)
                {
                    RotatedRect rect = minAreaRect(contours[i]);
                    float angle = 0;
                    if (angle < 0) angle += 180;
                    if (rect.size.width < rect.size.height)
                    {
                        angle = rect.angle;
                        angle -= 90;
                        if (angle < 0) angle += 180;
                    }
                    else
                    {
                        angle = rect.angle;
                    }
                    if (angle >= mind && angle <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_ELLIPSE_RA)
                {
                    if (contours[i].size() < 5)
                    {
                        isAnd &= false;
                        isOr |= false;
                        continue;
                    }
                    RotatedRect rect = cv::fitEllipse(contours[i]);
                    double len = rect.size.width;
                    if (rect.size.width < rect.size.height)
                        len = rect.size.height;
                    if (len/2 >= mind && len/2 <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_ELLIPSE_RB)
                {
                    if (contours[i].size() < 5)
                    {
                        isAnd &= false;
                        isOr |= false;
                        continue;
                    }
                    RotatedRect rect = cv::fitEllipse(contours[i]);
                    double len = rect.size.height;
                    if (rect.size.width < rect.size.height)
                        len = rect.size.width;
                    if (len/2 >= mind && len/2 <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
                else if (types[j] == SELECT_ELLIPSE_PHI)
                {
                    if (contours[i].size() < 5)
                    {
                        isAnd &= false;
                        isOr |= false;
                        continue;
                    }
                    RotatedRect rect = cv::fitEllipse(contours[i]);
                    float angle = 0;
                    if (angle < 0) angle += 180;
                    if (rect.size.width < rect.size.height)
                    {
                        angle = rect.angle;
                        angle -= 90;
                        if (angle < 0) angle += 180;
                    }
                    else
                    {
                        angle = rect.angle;
                    }
                    if (angle >= mind && angle <= maxd)
                    {
                        isAnd &= true;
                        isOr |= true;
                    }
                    else
                    {
                        isAnd &= false;
                        isOr |= false;
                    }
                }
            }
            if (isAnd && operation == SELECT_AND)
                selectContours.push_back(contours[i]);
            if (isOr && operation == SELECT_OR)
                selectContours.push_back(contours[i]);
        }
    }, cur_td_n);

    drawContours(dst, selectContours, -1, Scalar(255), CV_FILLED);
    bitwise_and(src, dst, dst);
    return selectContours.size();
}
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值