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();
}
OpenCV实现halcon的select_shape函数
于 2021-06-30 16:40:51 首次发布