目录
9.opencv双阈值二值化---->Halcon的直方图双阈值二值化
1.opencv4.3.0与VS2019环境配置见:
https://blog.csdn.net/weixin_50016546/article/details/124770493
2.opencv4.3.0与QT5.14.2环境配置见:
QT5.14 [MSVC 2017编译版]与 OpenCV4.3.0 联编环境配置_NCUTer的博客-CSDN博客
- read_image (Image,'1.png')
- mean_image (Image,ImageMean,9,9)
- *动态阈值,也叫局部阈值
- dyn_threshold (Image, ImageMean, RegionDynThresh, 15, 'not_equal')
方案1:
- void dynthreshold_referHalcon(cv::Mat &frame_gray, int ksize, int offset) //仿Halcon
- {
- cv::Mat srcMean;
- cv::Mat RegionDynThresh;
-
- //均值滤波
- blur(frame_gray, srcMean, cv::Size(9, 9));
-
- //动态阈值
- RegionDynThresh = cv::Mat::zeros(frame_gray.size(), CV_8UC1);
- DynThreshold(frame_gray, srcMean, RegionDynThresh, offset, Equal);
- }
-
-
- void DynThreshold(cv::Mat &src, cv::Mat &srcMean, cv::Mat &result, int offset, int LightDark)
- {
- //使用Opencv实现Halcon中的动态阈值
- //src是原图,灰度图
- //srcMean是平滑滤波之后的图
- //最好不要把Offset这个变量设置为0,因为这样会导致最后找到太多很小的regions,而这基本上都是噪声。
- //所以这个值最好是在5-40之间,值选择的越大,提取出来的regions就会越小。
- int r = src.rows; //高
- int c = src.cols; //宽
- int Value = 0;
- for (int i = 0; i < r; i++)
- {
- uchar *datasrc = src.ptr<uchar>(i); //指针访问图像像素
- uchar *datasrcMean = srcMean.ptr<uchar>(i);
- uchar *dataresult = result.ptr<uchar>(i);
-
- for (int j = 0; j < c; j++)
- {
- switch (LightDark)
- {
- case Light:
- Value = datasrc[j] - datasrcMean[j];
- if (Value >= offset)
- {
- dataresult[j] = 255;
- }
- break;
-
- case Dark:
- Value = datasrcMean[j] - datasrc[j];
- if (Value >= offset)
- {
- dataresult[j] = 255;
- }
- break;
-
- case Equal:
- Value = datasrc[j] - datasrcMean[j];
- if (Value >= -offset && Value <= offset)
- {
- dataresult[j] = 255;
- }
- break;
-
- case Not_equal:
- Value = datasrc[j] - datasrcMean[j];
- if (Value < -offset || Value > offset)
- {
- dataresult[j] = 255;
- }
- break;
-
- default:
- break;
- }
- }
- }
- }
方案2:
- enum ThresholdType
- {
- THRESHOLD_LIGHT, //明
- THRESHOLD_DARK, //暗
- THRESHOLD_EQUAL, //等于
- THRESHOLD_NOT_EQUAL //不等于
- };
-
- //功能:使用局部阈值分割图像
- //参数:
- // src:输入图像
- // pre:包含本地阈值的图像(一般可使用均值滤波后的图像)
- // dst:输出图像
- // offset:灰度偏移量(-255 ≤ offset ≤ 255)
- // type:
- // THRESHOLD_LIGHT(明): g_src ≥ g_pre + offset
- // THRESHOLD_DARK(暗): g_src ≤ g_pre - offset
- // THRESHOLD_EQUAL(等于): g_pre - offset ≤ g_src ≤ g_pre + offset
- // THRESHOLD_NOT_EQUAL(不等于): g_pre - offset > g_src || g_src > g_pre + offset
- //返回值:无
- void dyn_threshold(Mat src, Mat pre, Mat &dst, int offset, ThresholdType type)
- {
- dst = Mat(src.size(), CV_8UC1, Scalar(0));
- int pixelsCount = src.rows * src.cols;
-
- for(int i = 0;i < pixelsCount; i++)
- {
- int g_src = src.data[i];
- int g_pre = pre.data[i];
- if (type == THRESHOLD_LIGHT)
- {
- if (g_src >= g_pre + offset)
- dst.data[i] = 255;
- }
- else if (type == THRESHOLD_DARK)
- {
- if (g_src <= g_pre - offset)
- dst.data[i] = 255;
- }
- else if (type == THRESHOLD_EQUAL)
- {
- if (g_src >= g_pre - offset && g_src <= g_pre + offset)
- dst.data[i] = 255;
- }
- else if (type == THRESHOLD_NOT_EQUAL)
- {
- if (g_src < g_pre - offset || g_src > g_pre + offset)
- dst.data[i] = 255;
- }
- }
- }
Halcon算子: emphasize(img,outputimg,20,20,2)
- void emphasize(const cv::Mat &input, cv::Mat &output, int MaskWidth, int MaskHeight, float Factor)
- {
- //公式res := round((orig - mean) * Factor) + orig
- //等价于在MaskHeight、MaskWidth的空间内中心化后增加方差
- cv::Mat mean;
-
- //等价于求指定范围窗口内的均值
- cv::blur(input, mean, cv::Size(MaskWidth, MaskHeight));
- output.create(input.size(), input.type());
- if (input.type() == CV_8UC1)
- {
- for (int i = 0; i < input.rows; i++)
- {
- const uchar *rptr = input.ptr<uchar>(i);
- uchar *mptr = mean.ptr<uchar>(i);
- uchar *optr = output.ptr<uchar>(i);
- for (int j = 0; j < input.cols; j++)
- {
- optr[j] = cv::saturate_cast<uchar>(round((rptr[j] - mptr[j]) * Factor) + rptr[j] * 1.0f);
- }
- }
- }
- else if (input.type() == CV_8UC3)
- {
- for (int i = 0; i < input.rows; i++)
- {
- const uchar *rptr = input.ptr<uchar>(i);
- uchar *mptr = mean.ptr<uchar>(i);
- uchar *optr = output.ptr<uchar>(i);
- for (int j = 0; j < input.cols; j++)
- {
- //饱和转换 小于0的值会被置为0 大于255的值会被置为255
- optr[j * 3] = cv::saturate_cast<uchar>(round((rptr[j * 3] - mptr[j * 3]) * Factor) + rptr[j * 3] * 1.0f);
- optr[j * 3 + 1] = cv::saturate_cast<uchar>(round((rptr[j * 3 + 1] - mptr[j * 3 + 1]) * Factor) + rptr[j * 3 + 1] * 1.0f);
- optr[j * 3 + 2] = cv::saturate_cast<uchar>(round((rptr[j * 3 + 2] - mptr[j * 3 + 2]) * Factor) + rptr[j * 3 + 2] * 1.0f);
- }
- }
- }
- }
read_image (Image, '1.jpg')
rgb1_to_gray (Image, GrayImage)
threshold (GrayImage, Regions, 43, 120)
connection (Regions, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 150, 666)
select_shape (SelectedRegions, SelectedRegions1, 'circularity', 'and', 0.45, 1)
opencv实现:
方案1:
- #include "stdafx.h"
- #include <iostream>
- #include "opencv2/core/core.hpp"
- #include "opencv2/highgui/highgui.hpp"
- #include "opencv2/imgproc/imgproc.hpp"
- using namespace std;
- using namespace cv;
- #define VP vector<Point> //用VP符号代替 vector<point>
-
- RNG rng (12345);
-
- //带有上下限的threshold
- void threshold2(Mat gray,Mat& thresh,int minvalue,int maxvalue)
- {
- Mat thresh1;
- Mat thresh2;
- threshold(gray,thresh1,43,255, THRESH_BINARY);
- threshold(gray,thresh2,111,255,THRESH_BINARY_INV);
- thresh = thresh1 & thresh2;
- }
-
- //寻找并绘制出联通区域
- vector<vector<point>> connection2(Mat src,Mat& draw)
- {
- draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
- vector<vector<point>>contours;
- findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
- for (int i=0;i<contours.size();i++)
- {
- Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
- drawContours(draw,contours,i,color,-1);
- }
- return contours;
- }
- //select_shape
- vector<vector<point>> selectShapeArea(Mat src,Mat& draw,vector<VP> contours,int minvalue,int maxvalue)
- {
- vector<vector<point>> result_contours;
- draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
- for (int i=0;i<contours.size();i++)
- {
- int countour_area = contourArea(contours[i]);
- if (countour_area >minvalue && countour_area<maxvalue)
- {
- result_contours.push_back(contours[i]);
- }
- }
- for (int i=0;i<result_contours.size();i++)
- {
- Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
- drawContours(draw,result_contours,i,color,-1);
- }
- return result_contours;
- }
- //计算轮廓的圆的特性
- float calculateCircularity(vector<point> contour)
- {
- Point2f center;
- float radius = 0;
- minEnclosingCircle((Mat)contour,center,radius);
- //以最小外接圆半径作为数学期望,计算轮廓上各点到圆心距离的标准差
- float fsum = 0;
- float fcompare = 0;
- for (int i=0;i<contour.size();i++)
- {
- Point2f ptmp = contour[i];
- float fdistenct = sqrt((float)((ptmp.x - center.x)*(ptmp.x - center.x)+(ptmp.y - center.y)*(ptmp.y-center.y)));
- float fdiff = abs(fdistenct - radius);
- fsum = fsum + fdiff;
- }
- fcompare = fsum/(float)contour.size();
- return fcompare;
- }
- //select_shape
- vector<vector<point>> selectShapeCircularity(Mat src,Mat& draw,vector<VP> contours,float minvalue,float maxvalue)
- {
- vector<vector<point>> result_contours;
- draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
- for (int i=0;i<contours.size();i++)
- {
- float fcompare = calculateCircularity(contours[i]);
- if (fcompare >=minvalue && fcompare <=maxvalue)
- {
- result_contours.push_back(contours[i]);
- }
- }
- for (int i=0;i<result_contours.size();i++)
- {
- Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
- drawContours(draw,result_contours,i,color,-1);
- }
- return result_contours;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- Mat src;
- Mat gray;
- Mat thresh;
- Mat draw_connection;
- Mat draw_area;
- Mat draw_circle;
- vector<vector<point>>contours_connection;
- vector<vector<point>>contours_area;
- vector<vector<point>>contours_circle;
- vector<vector<point>>contours_tmp;
- //read_image (Image1, '1.jpg')
- src = imread("1.jpg");
- //rgb1_to_gray (Image1, GrayImage)
- cvtColor(src,gray,COLOR_BGR2GRAY);
- //threshold (GrayImage, Regions, 43, 111)
- threshold2(gray,thresh,43,111);
- //connection (Regions, ConnectedRegions)
- contours_connection = connection2(thresh.clone(),draw_connection);
- //select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 150, 666)
- contours_area = selectShapeArea(thresh.clone(),draw_area,contours_connection,150,666);
- //select_shape (SelectedRegions, SelectedRegions1, 'circularity', 'and', 0.45, 1)
- contours_circle = selectShapeCircularity(thresh.clone(),draw_circle,contours_area,1,6);
- //显示结果
- imshow("src",src);
- imshow("thresh",thresh);
- imshow("draw_connection",draw_connection);
- imshow("draw_area",draw_area);
- imshow("draw_circle",draw_circle);
- waitKey();
- }
方案2:
-
-
- 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;
- for (int i = 0; i < cnum; 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)
- {
- 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 (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;
- Point2f center;
- area_center(temp, area, center);
- RotatedRect rect = minAreaRect(contours[i]);
- 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]);
- }
- drawContours(dst, selectContours, -1, Scalar(255), CV_FILLED);
- bitwise_and(src, dst, dst);
- return selectContours.size();
- }
- void method_1(Mat &image) {
- double t1 = getTickCount();
- int w = image.cols;
- int h = image.rows;
- for (int row = 0; row < h; row++) {
- for (int col = 0; col < w; col++) {
- Vec3b bgr = image.at<Vec3b>(row, col);
- bgr[0] = 255 - bgr[0];
- bgr[1] = 255 - bgr[1];
- bgr[2] = 255 - bgr[2];
- image.at<Vec3b>(row, col) = bgr;
- }
- }
- double t2 = getTickCount();
- double t = ((t2 - t1) / getTickFrequency()) * 1000;
- ostringstream ss;
- ss << "Execute time : " << std::fixed << std::setprecision(2) << t << " ms ";
- putText(image, ss.str(), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);
- imshow("result", image);
- }
- //功能:填充区域中的孔洞
- //参数:
- // src:输入图像
- // dst:输出图像
- //返回值:无
- void fill_up(Mat src, Mat &dst)
- {
- dst = Mat(src.size(), CV_8UC1, Scalar(0));
- vector<vector<Point>> contours;
- findContours(src, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
- drawContours(dst, contours, -1, Scalar(255), CV_FILLED);
- }
- //功能:求图中像素值为255的斑块面积和重心坐标
- //参数:
- // src:输入图像
- // area:图中像素值为255的像素个数
- // center:斑块的重心坐标
- //返回值:无
- void area_center(Mat src, int &area, Point2f ¢er)
- {
- int pixelsCount = src.rows * src.cols;
- area = 0;
- center = Point2f(0, 0);
- float centerX = 0;
- float centerY = 0;
- int mcol = src.cols;
- for(int i=0;i<pixelsCount;i++)
- {
- if(src.data[i] == 255)
- {
- area++;
-
- int x = i % mcol;
- int y = i / mcol;
-
- centerX += x;
- centerY += y;
- }
- }
- if (area > 0)
- {
- centerX /= area;
- centerY /= area;
- center = Point2f(centerX, centerY);
- }
- }
-
- enum SortCriterion
- {
- FIRST_POINT, //区域第一行的最左侧的点
- LAST_POINT, //区域最后一行的最右侧的点
- UPPER_LEFT, //区域周围矩形的左上角
- UPPER_RIGHT, //区域周围矩形的右上角
- LOWER_LEFT, //区域周围矩形的左下角
- LOWER_RIGHT //区域周围矩形的右下角
- };
-
- enum SortDirection
- {
- ROW, //区域按行排列,即从左到右,从上到下
- COLUMN //区域按列排列,即从上到下,从左到右
- };
-
- //功能:由区域的相对位置对区域进行排序
- //参数:
- // src:输入图像
- // contours:输入图像中的轮廓组
- // pos:已排序的轮廓索引
- // sc:排序基准点
- // isDue:
- // true:从小到大进行排序
- // false:从大到小进行排序
- // sd:排序方向
- //返回值:true:排序成功
- // false:排序失败
- bool sort_region(Mat src,vector<vector<Point>> contours, vector<int> &pos,
- SortCriterion sc, bool isDue, SortDirection sd)
- {
- int count = contours.size();
- pos.resize(count);
- vector<Point> points;
- for (int i = 0; i < count; i++)
- {
- pos[i] = i;
- Rect rect = boundingRect(contours[i]);
- if (sc == FIRST_POINT)
- {
- int row = rect.y;
- for (int col = rect.x; col <= rect.x + rect.width; col++)
- {
- if (src.at<uchar>(row, col) > 0)
- {
- points.push_back(Point(col, row));
- break;
- }
- }
- }
- else if (sc == LAST_POINT)
- {
- int row = rect.y + rect.height;
- for (int col = rect.x + rect.width; col >= rect.x; col--)
- {
- if (src.at<uchar>(row, col) > 0)
- {
- points.push_back(Point(col, row));
- break;
- }
- }
- }
- else if (sc == UPPER_LEFT)
- points.push_back(rect.tl());
- else if (sc == UPPER_RIGHT)
- points.push_back(Point(rect.x + rect.width, rect.y));
- else if (sc == LOWER_LEFT)
- points.push_back(Point(rect.x, rect.y + rect.height));
- else if (sc == LOWER_RIGHT)
- points.push_back(rect.br());
- }
- int np = points.size();
- if (np != count)
- return false;
- if (sd == ROW)
- {
- for (int i = 0; i < count - 1; i++)
- {
- for (int j = 0; j < count - 1 - i; j++)
- {
- if (isDue)
- {
- if (points[j].y > points[j + 1].y)
- {
- Point temp = points[j];
- points[j] = points[j + 1];
- points[j + 1] = temp;
-
- int index = pos[j];
- pos[j] = pos[j + 1];
- pos[j + 1] = index;
- }
- }
- else
- {
- if (points[j].y < points[j + 1].y)
- {
- Point temp = points[j];
- points[j] = points[j + 1];
- points[j + 1] = temp;
-
- int index = pos[j];
- pos[j] = pos[j + 1];
- pos[j + 1] = index;
- }
- }
- }
- }
- for (int i = 0; i < count - 1; i++)
- {
- for (int j = 0; j < count - 1 - i; j++)
- {
- if (points[j].y == points[j + 1].y)
- {
- if (isDue)
- {
- if (points[j].x > points[j + 1].x)
- {
- Point temp = points[j];
- points[j] = points[j + 1];
- points[j + 1] = temp;
-
- int index = pos[j];
- pos[j] = pos[j + 1];
- pos[j + 1] = index;
- }
- }
- else
- {
- if (points[j].x < points[j + 1].x)
- {
- Point temp = points[j];
- points[j] = points[j + 1];
- points[j + 1] = temp;
-
- int index = pos[j];
- pos[j] = pos[j + 1];
- pos[j + 1] = index;
- }
- }
- }
- }
- }
- }
- else if (sd == COLUMN)
- {
- for (int i = 0; i < count - 1; i++)
- {
- for (int j = 0; j < count - 1 - i; j++)
- {
- if (isDue)
- {
- if (points[j].x > points[j + 1].x)
- {
- Point temp = points[j];
- points[j] = points[j + 1];
- points[j + 1] = temp;
-
- int index = pos[j];
- pos[j] = pos[j + 1];
- pos[j + 1] = index;
- }
- }
- else
- {
- if (points[j].x < points[j + 1].x)
- {
- Point temp = points[j];
- points[j] = points[j + 1];
- points[j + 1] = temp;
-
- int index = pos[j];
- pos[j] = pos[j + 1];
- pos[j + 1] = index;
- }
- }
- }
- }
- for (int i = 0; i < count - 1; i++)
- {
- for (int j = 0; j < count - 1 - i; j++)
- {
- if (points[j].x == points[j + 1].x)
- {
- if (isDue)
- {
- if (points[j].y > points[j + 1].y)
- {
- Point temp = points[j];
- points[j] = points[j + 1];
- points[j + 1] = temp;
-
- int index = pos[j];
- pos[j] = pos[j + 1];
- pos[j + 1] = index;
- }
- }
- else
- {
- if (points[j].y < points[j + 1].y)
- {
- Point temp = points[j];
- points[j] = points[j + 1];
- points[j + 1] = temp;
-
- int index = pos[j];
- pos[j] = pos[j + 1];
- pos[j + 1] = index;
- }
- }
- }
- }
- }
- }
- return true;
- }
-
- enum ShapeTransType
- {
- SHAPETRANS_RECTANGLE, //平行于坐标轴的最小外接矩形
- SHAPETRANS_CIRCLE, //最小外接圆
- SHAPETRANS_CONVER //凸包
- };
-
- //功能:变换区域的形状
- //参数:
- // src:输入图像
- // dst:输出图像
- // type:变换形状
- //返回值:无
- void shape_trans(Mat src, Mat &dst, ShapeTransType type)
- {
- dst = Mat(src.size(), CV_8UC1, Scalar(0));
- vector<vector<Point>> contours;
- findContours(src, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
- int n = contours.size();
- for (int i = 0; i < n; i++)
- {
- if (type == SHAPETRANS_RECTANGLE)
- {
- Rect rect = boundingRect(contours[i]);
- rectangle (dst, rect, Scalar(255), CV_FILLED);
- }
- else if (type == SHAPETRANS_CIRCLE)
- {
- Point2f center;
- float radius;
- minEnclosingCircle(contours[i], center, radius);
- circle (dst, center, radius, Scalar(255), CV_FILLED);
- }
- else if (type == SHAPETRANS_CONVER)
- {
- vector<Point> conver;
- convexHull(contours[i], conver);
-
- vector<vector<Point>> pconver;
- pconver.push_back(conver);
-
- fillPoly(dst, pconver, Scalar(255));
- }
- }
- }
-
halcon算子:
threshold(img , region , 40 , 160 )
- //正向阈值二值化与反向阈值二值化按位与操作取交集
- Mat src= imread("1.png");
- Mat m1, m2, dst;
- threshold(src, m1, 40, 255, cv::THRESH_BINARY);
- threshold(src, m2, 160, 255, cv::THRESH_BINARY_INV);
- bitwise_and(m1, m2, dst);
- void Threshold(cv::Mat &src, cv::Mat &dst, int lowThresh, int highThresh)
- {
- if(src.empty())
- {
- std::cout<<"src is empty"<<std::endl;
- return;
- }
- dst = cv::Mat::zeros(src.size(), src.type());
- double t = (double)cv::getTickCount();
-
- for(int i = 0; i < src.rows; i++)
- {
- uchar *srcPt = (uchar*)src.data + i * src.step;
- uchar *dstPt = (uchar*)dst.data + i * dst.step;
-
- for(int j = 0; j < src.cols; j++)
- {
- uchar pixel = *srcPt++;
- if(pixel > lowThresh && pixel < highThresh)
- *dstPt = 255;
- dstPt++;
- }
- }
- t = ((double)cv::getTickCount() - t) / cv::getTickFrequency()*1000; //获得时间,单位是毫秒
- cout <<"耗时:"<< t<<"ms"<<endl;
- }
-
- //halcon gray_range_rect算子的C++实现
- void gray_range_rect(Mat &src, Mat &dst, Size size)
- {
- //图像边界扩充
- int hh = (size.height - 1) / 2;
- int hw = (size.width - 1) / 2;
- cv::Mat Newsrc;
- cv::copyMakeBorder(src, Newsrc, hh, hh, hw, hw, cv::BORDER_REFLECT_101);//以边缘为轴,对称
- dst = cv::Mat::zeros(src.rows, src.cols, src.type());
-
- //遍历图像
- for (int i = 0; i < src.rows; i++)
- {
- for (int j = 0; j < src.cols; j++)
- {
- //uchar srcValue = src.at<uchar>(i, j);
- int minValue = 255;
- int maxValue = 0;
- for (int k = 0; k < hh; k++)
- {
- for (int z = 0; z < hw; z++)
- {
- int srcValue = (int)Newsrc.at<uchar>(i + k, j + z);
- minValue = minValue > srcValue ? srcValue : minValue;
- maxValue = maxValue > srcValue ? maxValue : srcValue;
-
- }
- }
- uchar diffValue = (uchar)(maxValue - minValue);
- dst.at<uchar>(i, j) = diffValue;
- }
- }
- }
后续学习更新。。