• opencv [c++] OpenCV实现Halcon相关算子算法


    目录

     1.Dyn_threshold 动态阈值

     2.OpenCV实现

     2.Emphasize图像锐化增强处理

    3.select_shape()特征筛选

    4.opencv访问遍历图像的每一个像素方法

    5.Fill_up()区域填充算子

    6.Area_Center()计算区域面积与中心坐标

    7.sort_region()对区域进行排序

    8.shape_trans()区域转换算子

    9.opencv双阈值二值化---->Halcon的直方图双阈值二值化

     10.Gray_range_rect()图像灰度增强预处理


    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博客

     1.Dyn_threshold 动态阈值

    1. read_image (Image,'1.png')
    2. mean_image (Image,ImageMean,9,9)
    3. *动态阈值,也叫局部阈值
    4. dyn_threshold (Image, ImageMean, RegionDynThresh, 15, 'not_equal')

     2.OpenCV实现

    方案1:

    1. void dynthreshold_referHalcon(cv::Mat &frame_gray, int ksize, int offset) //仿Halcon
    2. {
    3. cv::Mat srcMean;
    4. cv::Mat RegionDynThresh;
    5. //均值滤波
    6. blur(frame_gray, srcMean, cv::Size(9, 9));
    7. //动态阈值
    8. RegionDynThresh = cv::Mat::zeros(frame_gray.size(), CV_8UC1);
    9. DynThreshold(frame_gray, srcMean, RegionDynThresh, offset, Equal);
    10. }
    11. void DynThreshold(cv::Mat &src, cv::Mat &srcMean, cv::Mat &result, int offset, int LightDark)
    12. {
    13. //使用Opencv实现Halcon中的动态阈值
    14. //src是原图,灰度图
    15. //srcMean是平滑滤波之后的图
    16. //最好不要把Offset这个变量设置为0,因为这样会导致最后找到太多很小的regions,而这基本上都是噪声。
    17. //所以这个值最好是在5-40之间,值选择的越大,提取出来的regions就会越小。
    18. int r = src.rows; //高
    19. int c = src.cols; //宽
    20. int Value = 0;
    21. for (int i = 0; i < r; i++)
    22. {
    23. uchar *datasrc = src.ptr<uchar>(i); //指针访问图像像素
    24. uchar *datasrcMean = srcMean.ptr<uchar>(i);
    25. uchar *dataresult = result.ptr<uchar>(i);
    26. for (int j = 0; j < c; j++)
    27. {
    28. switch (LightDark)
    29. {
    30. case Light:
    31. Value = datasrc[j] - datasrcMean[j];
    32. if (Value >= offset)
    33. {
    34. dataresult[j] = 255;
    35. }
    36. break;
    37. case Dark:
    38. Value = datasrcMean[j] - datasrc[j];
    39. if (Value >= offset)
    40. {
    41. dataresult[j] = 255;
    42. }
    43. break;
    44. case Equal:
    45. Value = datasrc[j] - datasrcMean[j];
    46. if (Value >= -offset && Value <= offset)
    47. {
    48. dataresult[j] = 255;
    49. }
    50. break;
    51. case Not_equal:
    52. Value = datasrc[j] - datasrcMean[j];
    53. if (Value < -offset || Value > offset)
    54. {
    55. dataresult[j] = 255;
    56. }
    57. break;
    58. default:
    59. break;
    60. }
    61. }
    62. }
    63. }

     方案2:

    1. enum ThresholdType
    2. {
    3. THRESHOLD_LIGHT, //明
    4. THRESHOLD_DARK, //暗
    5. THRESHOLD_EQUAL, //等于
    6. THRESHOLD_NOT_EQUAL //不等于
    7. };
    8. //功能:使用局部阈值分割图像
    9. //参数:
    10. // src:输入图像
    11. // pre:包含本地阈值的图像(一般可使用均值滤波后的图像)
    12. // dst:输出图像
    13. // offset:灰度偏移量(-255 ≤ offset ≤ 255)
    14. // type:
    15. // THRESHOLD_LIGHT(明): g_src ≥ g_pre + offset
    16. // THRESHOLD_DARK(暗): g_src ≤ g_pre - offset
    17. // THRESHOLD_EQUAL(等于): g_pre - offset ≤ g_src ≤ g_pre + offset
    18. // THRESHOLD_NOT_EQUAL(不等于): g_pre - offset > g_src || g_src > g_pre + offset
    19. //返回值:无
    20. void dyn_threshold(Mat src, Mat pre, Mat &dst, int offset, ThresholdType type)
    21. {
    22. dst = Mat(src.size(), CV_8UC1, Scalar(0));
    23. int pixelsCount = src.rows * src.cols;
    24. for(int i = 0;i < pixelsCount; i++)
    25. {
    26. int g_src = src.data[i];
    27. int g_pre = pre.data[i];
    28. if (type == THRESHOLD_LIGHT)
    29. {
    30. if (g_src >= g_pre + offset)
    31. dst.data[i] = 255;
    32. }
    33. else if (type == THRESHOLD_DARK)
    34. {
    35. if (g_src <= g_pre - offset)
    36. dst.data[i] = 255;
    37. }
    38. else if (type == THRESHOLD_EQUAL)
    39. {
    40. if (g_src >= g_pre - offset && g_src <= g_pre + offset)
    41. dst.data[i] = 255;
    42. }
    43. else if (type == THRESHOLD_NOT_EQUAL)
    44. {
    45. if (g_src < g_pre - offset || g_src > g_pre + offset)
    46. dst.data[i] = 255;
    47. }
    48. }
    49. }

     2.Emphasize图像锐化增强处理

      Halcon算子: emphasize(img,outputimg,20,20,2)

    1. void emphasize(const cv::Mat &input, cv::Mat &output, int MaskWidth, int MaskHeight, float Factor)
    2. {
    3. //公式res := round((orig - mean) * Factor) + orig
    4. //等价于在MaskHeight、MaskWidth的空间内中心化后增加方差
    5. cv::Mat mean;
    6. //等价于求指定范围窗口内的均值
    7. cv::blur(input, mean, cv::Size(MaskWidth, MaskHeight));
    8. output.create(input.size(), input.type());
    9. if (input.type() == CV_8UC1)
    10. {
    11. for (int i = 0; i < input.rows; i++)
    12. {
    13. const uchar *rptr = input.ptr<uchar>(i);
    14. uchar *mptr = mean.ptr<uchar>(i);
    15. uchar *optr = output.ptr<uchar>(i);
    16. for (int j = 0; j < input.cols; j++)
    17. {
    18. optr[j] = cv::saturate_cast<uchar>(round((rptr[j] - mptr[j]) * Factor) + rptr[j] * 1.0f);
    19. }
    20. }
    21. }
    22. else if (input.type() == CV_8UC3)
    23. {
    24. for (int i = 0; i < input.rows; i++)
    25. {
    26. const uchar *rptr = input.ptr<uchar>(i);
    27. uchar *mptr = mean.ptr<uchar>(i);
    28. uchar *optr = output.ptr<uchar>(i);
    29. for (int j = 0; j < input.cols; j++)
    30. {
    31. //饱和转换 小于0的值会被置为0 大于255的值会被置为255
    32. optr[j * 3] = cv::saturate_cast<uchar>(round((rptr[j * 3] - mptr[j * 3]) * Factor) + rptr[j * 3] * 1.0f);
    33. optr[j * 3 + 1] = cv::saturate_cast<uchar>(round((rptr[j * 3 + 1] - mptr[j * 3 + 1]) * Factor) + rptr[j * 3 + 1] * 1.0f);
    34. optr[j * 3 + 2] = cv::saturate_cast<uchar>(round((rptr[j * 3 + 2] - mptr[j * 3 + 2]) * Factor) + rptr[j * 3 + 2] * 1.0f);
    35. }
    36. }
    37. }
    38. }

    3.select_shape()特征筛选

    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:

    1. #include "stdafx.h"
    2. #include <iostream>
    3. #include "opencv2/core/core.hpp"
    4. #include "opencv2/highgui/highgui.hpp"
    5. #include "opencv2/imgproc/imgproc.hpp"
    6. using namespace std;
    7. using namespace cv;
    8. #define VP vector<Point> //用VP符号代替 vector<point>
    9. RNG rng (12345);
    10. //带有上下限的threshold
    11. void threshold2(Mat gray,Mat& thresh,int minvalue,int maxvalue)
    12. {
    13. Mat thresh1;
    14. Mat thresh2;
    15. threshold(gray,thresh1,43,255, THRESH_BINARY);
    16. threshold(gray,thresh2,111,255,THRESH_BINARY_INV);
    17. thresh = thresh1 & thresh2;
    18. }
    19. //寻找并绘制出联通区域
    20. vector<vector<point>> connection2(Mat src,Mat& draw)
    21. {
    22. draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
    23. vector<vector<point>>contours;
    24. findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
    25. for (int i=0;i<contours.size();i++)
    26. {
    27. Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
    28. drawContours(draw,contours,i,color,-1);
    29. }
    30. return contours;
    31. }
    32. //select_shape
    33. vector<vector<point>> selectShapeArea(Mat src,Mat& draw,vector<VP> contours,int minvalue,int maxvalue)
    34. {
    35. vector<vector<point>> result_contours;
    36. draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
    37. for (int i=0;i<contours.size();i++)
    38. {
    39. int countour_area = contourArea(contours[i]);
    40. if (countour_area >minvalue && countour_area<maxvalue)
    41. {
    42. result_contours.push_back(contours[i]);
    43. }
    44. }
    45. for (int i=0;i<result_contours.size();i++)
    46. {
    47. Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
    48. drawContours(draw,result_contours,i,color,-1);
    49. }
    50. return result_contours;
    51. }
    52. //计算轮廓的圆的特性
    53. float calculateCircularity(vector<point> contour)
    54. {
    55. Point2f center;
    56. float radius = 0;
    57. minEnclosingCircle((Mat)contour,center,radius);
    58. //以最小外接圆半径作为数学期望,计算轮廓上各点到圆心距离的标准差
    59. float fsum = 0;
    60. float fcompare = 0;
    61. for (int i=0;i<contour.size();i++)
    62. {
    63. Point2f ptmp = contour[i];
    64. float fdistenct = sqrt((float)((ptmp.x - center.x)*(ptmp.x - center.x)+(ptmp.y - center.y)*(ptmp.y-center.y)));
    65. float fdiff = abs(fdistenct - radius);
    66. fsum = fsum + fdiff;
    67. }
    68. fcompare = fsum/(float)contour.size();
    69. return fcompare;
    70. }
    71. //select_shape
    72. vector<vector<point>> selectShapeCircularity(Mat src,Mat& draw,vector<VP> contours,float minvalue,float maxvalue)
    73. {
    74. vector<vector<point>> result_contours;
    75. draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
    76. for (int i=0;i<contours.size();i++)
    77. {
    78. float fcompare = calculateCircularity(contours[i]);
    79. if (fcompare >=minvalue && fcompare <=maxvalue)
    80. {
    81. result_contours.push_back(contours[i]);
    82. }
    83. }
    84. for (int i=0;i<result_contours.size();i++)
    85. {
    86. Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
    87. drawContours(draw,result_contours,i,color,-1);
    88. }
    89. return result_contours;
    90. }
    91. int _tmain(int argc, _TCHAR* argv[])
    92. {
    93. Mat src;
    94. Mat gray;
    95. Mat thresh;
    96. Mat draw_connection;
    97. Mat draw_area;
    98. Mat draw_circle;
    99. vector<vector<point>>contours_connection;
    100. vector<vector<point>>contours_area;
    101. vector<vector<point>>contours_circle;
    102. vector<vector<point>>contours_tmp;
    103. //read_image (Image1, '1.jpg')
    104. src = imread("1.jpg");
    105. //rgb1_to_gray (Image1, GrayImage)
    106. cvtColor(src,gray,COLOR_BGR2GRAY);
    107. //threshold (GrayImage, Regions, 43, 111)
    108. threshold2(gray,thresh,43,111);
    109. //connection (Regions, ConnectedRegions)
    110. contours_connection = connection2(thresh.clone(),draw_connection);
    111. //select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 150, 666)
    112. contours_area = selectShapeArea(thresh.clone(),draw_area,contours_connection,150,666);
    113. //select_shape (SelectedRegions, SelectedRegions1, 'circularity', 'and', 0.45, 1)
    114. contours_circle = selectShapeCircularity(thresh.clone(),draw_circle,contours_area,1,6);
    115. //显示结果
    116. imshow("src",src);
    117. imshow("thresh",thresh);
    118. imshow("draw_connection",draw_connection);
    119. imshow("draw_area",draw_area);
    120. imshow("draw_circle",draw_circle);
    121. waitKey();
    122. }

     方案2:

    1. enum SelectShapeType
    2. {
    3. SELECT_AREA, //选中区域面积
    4. SELECT_RECTANGULARITY, //选中区域矩形度
    5. SELECT_WIDTH, //选中区域宽度(平行于坐标轴)
    6. SELECT_HEIGHT, //选中区域高度(平行于坐标轴)
    7. SELECT_ROW, //选中区域中心行索引
    8. SELECT_COLUMN, //选中区域中心列索引
    9. SELECT_RECT2_LEN1, //选中区域最小外接矩形的一半长度
    10. SELECT_RECT2_LEN2, //选中区域最小外接矩形的一半宽度
    11. SELECT_RECT2_PHI, //选中区域最小外接矩形的方向
    12. SELECT_ELLIPSE_RA, //选中区域外接椭圆的长半轴
    13. SELECT_ELLIPSE_RB, //选中区域外接椭圆的短半轴
    14. SELECT_ELLIPSE_PHI //选中区域外接椭圆的方向
    15. };
    16. enum SelectOperation
    17. {
    18. SELECT_AND, //与
    19. SELECT_OR //或
    20. };
    21. //功能:借助形状特征选择区域
    22. //参数:
    23. // src:输入图像
    24. // dst:输出图像
    25. // types:要检查的形状特征
    26. // operation:各个要素的链接类型(与、或)
    27. // mins:下限值
    28. // maxs:上限值
    29. //返回值:无
    30. int select_shape(Mat src, Mat &dst,
    31. vector<SelectShapeType> types,
    32. SelectOperation operation,
    33. vector<double> mins,
    34. vector<double> maxs)
    35. {
    36. if (!(types.size() == mins.size() && mins.size() == maxs.size()))
    37. return 0;
    38. int num = types.size();
    39. dst = Mat(src.size(), CV_8UC1, Scalar(0));
    40. vector<vector<Point>> contours;
    41. findContours(src, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    42. int cnum = contours.size();
    43. vector<vector<Point>> selectContours;
    44. for (int i = 0; i < cnum; i++)
    45. {
    46. bool isAnd = true;
    47. bool isOr = false;
    48. for (int j = 0; j < num; j++)
    49. {
    50. double mind = mins[j];
    51. double maxd = maxs[j];
    52. if (mind > maxd)
    53. {
    54. mind = maxs[j];
    55. maxd = mins[j];
    56. }
    57. if (types[j] == SELECT_AREA)
    58. {
    59. Mat temp = Mat(src.size(), CV_8UC1, Scalar(0));
    60. vector<vector<Point>> pconver;
    61. pconver.push_back(contours[i]);
    62. drawContours(temp, pconver, -1, Scalar(255), CV_FILLED);
    63. bitwise_and(src, temp, temp);
    64. int area;
    65. Point2f center;
    66. area_center(temp, area, center);
    67. if (area >= mind && area <= maxd)
    68. {
    69. isAnd &= true;
    70. isOr |= true;
    71. }
    72. else
    73. {
    74. isAnd &= false;
    75. isOr |= false;
    76. }
    77. }
    78. else if (types[j] == SELECT_RECTANGULARITY)
    79. {
    80. Mat temp = Mat(src.size(), CV_8UC1, Scalar(0));
    81. vector<vector<Point>> pconver;
    82. pconver.push_back(contours[i]);
    83. drawContours(temp, pconver, -1, Scalar(255), CV_FILLED);
    84. bitwise_and(src, temp, temp);
    85. int area;
    86. Point2f center;
    87. area_center(temp, area, center);
    88. RotatedRect rect = minAreaRect(contours[i]);
    89. double rectangularity = area / rect.size.area();
    90. if (rectangularity >= mind && rectangularity <= maxd)
    91. {
    92. isAnd &= true;
    93. isOr |= true;
    94. }
    95. else
    96. {
    97. isAnd &= false;
    98. isOr |= false;
    99. }
    100. }
    101. else if (types[j] == SELECT_WIDTH)
    102. {
    103. Rect rect = boundingRect(contours[i]);
    104. if (rect.width >= mind && rect.width <= maxd)
    105. {
    106. isAnd &= true;
    107. isOr |= true;
    108. }
    109. else
    110. {
    111. isAnd &= false;
    112. isOr |= false;
    113. }
    114. }
    115. else if (types[j] == SELECT_HEIGHT)
    116. {
    117. Rect rect = boundingRect(contours[i]);
    118. if (rect.height >= mind && rect.height <= maxd)
    119. {
    120. isAnd &= true;
    121. isOr |= true;
    122. }
    123. else
    124. {
    125. isAnd &= false;
    126. isOr |= false;
    127. }
    128. }
    129. else if (types[j] == SELECT_ROW)
    130. {
    131. Mat temp = Mat(src.size(), CV_8UC1, Scalar(0));
    132. vector<vector<Point>> pconver;
    133. pconver.push_back(contours[i]);
    134. drawContours(temp, pconver, -1, Scalar(255), CV_FILLED);
    135. bitwise_and(src, temp, temp);
    136. int area;
    137. Point2f center;
    138. area_center(temp, area, center);
    139. if (center.y >= mind && center.y <= maxd)
    140. {
    141. isAnd &= true;
    142. isOr |= true;
    143. }
    144. else
    145. {
    146. isAnd &= false;
    147. isOr |= false;
    148. }
    149. }
    150. else if (types[j] == SELECT_COLUMN)
    151. {
    152. Mat temp = Mat(src.size(), CV_8UC1, Scalar(0));
    153. vector<vector<Point>> pconver;
    154. pconver.push_back(contours[i]);
    155. drawContours(temp, pconver, -1, Scalar(255), CV_FILLED);
    156. bitwise_and(src, temp, temp);
    157. int area;
    158. Point2f center;
    159. area_center(temp, area, center);
    160. if (center.x >= mind && center.x <= maxd)
    161. {
    162. isAnd &= true;
    163. isOr |= true;
    164. }
    165. else
    166. {
    167. isAnd &= false;
    168. isOr |= false;
    169. }
    170. }
    171. else if (types[j] == SELECT_RECT2_LEN1)
    172. {
    173. RotatedRect rect = minAreaRect(contours[i]);
    174. double len = rect.size.width;
    175. if (rect.size.width < rect.size.height)
    176. len = rect.size.height;
    177. if (len / 2 >= mind && len / 2 <= maxd)
    178. {
    179. isAnd &= true;
    180. isOr |= true;
    181. }
    182. else
    183. {
    184. isAnd &= false;
    185. isOr |= false;
    186. }
    187. }
    188. else if (types[j] == SELECT_RECT2_LEN2)
    189. {
    190. RotatedRect rect = minAreaRect(contours[i]);
    191. double len = rect.size.height;
    192. if (rect.size.width < rect.size.height)
    193. len = rect.size.width;
    194. if (len / 2 >= mind && len / 2 <= maxd)
    195. {
    196. isAnd &= true;
    197. isOr |= true;
    198. }
    199. else
    200. {
    201. isAnd &= false;
    202. isOr |= false;
    203. }
    204. }
    205. else if (types[j] == SELECT_RECT2_PHI)
    206. {
    207. RotatedRect rect = minAreaRect(contours[i]);
    208. float angle = 0;
    209. if (angle < 0) angle += 180;
    210. if (rect.size.width < rect.size.height)
    211. {
    212. angle = rect.angle;
    213. angle -= 90;
    214. if (angle < 0) angle += 180;
    215. }
    216. else
    217. {
    218. angle = rect.angle;
    219. }
    220. if (angle >= mind && angle <= maxd)
    221. {
    222. isAnd &= true;
    223. isOr |= true;
    224. }
    225. else
    226. {
    227. isAnd &= false;
    228. isOr |= false;
    229. }
    230. }
    231. else if (types[j] == SELECT_ELLIPSE_RA)
    232. {
    233. if (contours[i].size() < 5)
    234. {
    235. isAnd &= false;
    236. isOr |= false;
    237. continue;
    238. }
    239. RotatedRect rect = cv::fitEllipse(contours[i]);
    240. double len = rect.size.width;
    241. if (rect.size.width < rect.size.height)
    242. len = rect.size.height;
    243. if (len / 2 >= mind && len / 2 <= maxd)
    244. {
    245. isAnd &= true;
    246. isOr |= true;
    247. }
    248. else
    249. {
    250. isAnd &= false;
    251. isOr |= false;
    252. }
    253. }
    254. else if (types[j] == SELECT_ELLIPSE_RB)
    255. {
    256. if (contours[i].size() < 5)
    257. {
    258. isAnd &= false;
    259. isOr |= false;
    260. continue;
    261. }
    262. RotatedRect rect = cv::fitEllipse(contours[i]);
    263. double len = rect.size.height;
    264. if (rect.size.width < rect.size.height)
    265. len = rect.size.width;
    266. if (len / 2 >= mind && len / 2 <= maxd)
    267. {
    268. isAnd &= true;
    269. isOr |= true;
    270. }
    271. else
    272. {
    273. isAnd &= false;
    274. isOr |= false;
    275. }
    276. }
    277. else if (types[j] == SELECT_ELLIPSE_PHI)
    278. {
    279. if (contours[i].size() < 5)
    280. {
    281. isAnd &= false;
    282. isOr |= false;
    283. continue;
    284. }
    285. RotatedRect rect = cv::fitEllipse(contours[i]);
    286. float angle = 0;
    287. if (angle < 0) angle += 180;
    288. if (rect.size.width < rect.size.height)
    289. {
    290. angle = rect.angle;
    291. angle -= 90;
    292. if (angle < 0) angle += 180;
    293. }
    294. else
    295. {
    296. angle = rect.angle;
    297. }
    298. if (angle >= mind && angle <= maxd)
    299. {
    300. isAnd &= true;
    301. isOr |= true;
    302. }
    303. else
    304. {
    305. isAnd &= false;
    306. isOr |= false;
    307. }
    308. }
    309. }
    310. if (isAnd && operation == SELECT_AND)
    311. selectContours.push_back(contours[i]);
    312. if (isOr && operation == SELECT_OR)
    313. selectContours.push_back(contours[i]);
    314. }
    315. drawContours(dst, selectContours, -1, Scalar(255), CV_FILLED);
    316. bitwise_and(src, dst, dst);
    317. return selectContours.size();
    318. }

    4.opencv访问遍历图像的每一个像素方法

    1. void method_1(Mat &image) {
    2. double t1 = getTickCount();
    3. int w = image.cols;
    4. int h = image.rows;
    5. for (int row = 0; row < h; row++) {
    6. for (int col = 0; col < w; col++) {
    7. Vec3b bgr = image.at<Vec3b>(row, col);
    8. bgr[0] = 255 - bgr[0];
    9. bgr[1] = 255 - bgr[1];
    10. bgr[2] = 255 - bgr[2];
    11. image.at<Vec3b>(row, col) = bgr;
    12. }
    13. }
    14. double t2 = getTickCount();
    15. double t = ((t2 - t1) / getTickFrequency()) * 1000;
    16. ostringstream ss;
    17. ss << "Execute time : " << std::fixed << std::setprecision(2) << t << " ms ";
    18. putText(image, ss.str(), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);
    19. imshow("result", image);
    20. }

    5.Fill_up()区域填充算子

    1. //功能:填充区域中的孔洞
    2. //参数:
    3. // src:输入图像
    4. // dst:输出图像
    5. //返回值:无
    6. void fill_up(Mat src, Mat &dst)
    7. {
    8. dst = Mat(src.size(), CV_8UC1, Scalar(0));
    9. vector<vector<Point>> contours;
    10. findContours(src, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    11. drawContours(dst, contours, -1, Scalar(255), CV_FILLED);
    12. }

    6.Area_Center()计算区域面积与中心坐标

    1. //功能:求图中像素值为255的斑块面积和重心坐标
    2. //参数:
    3. // src:输入图像
    4. // area:图中像素值为255的像素个数
    5. // center:斑块的重心坐标
    6. //返回值:无
    7. void area_center(Mat src, int &area, Point2f &center)
    8. {
    9. int pixelsCount = src.rows * src.cols;
    10. area = 0;
    11. center = Point2f(0, 0);
    12. float centerX = 0;
    13. float centerY = 0;
    14. int mcol = src.cols;
    15. for(int i=0;i<pixelsCount;i++)
    16. {
    17. if(src.data[i] == 255)
    18. {
    19. area++;
    20. int x = i % mcol;
    21. int y = i / mcol;
    22. centerX += x;
    23. centerY += y;
    24. }
    25. }
    26. if (area > 0)
    27. {
    28. centerX /= area;
    29. centerY /= area;
    30. center = Point2f(centerX, centerY);
    31. }
    32. }

    7.sort_region()对区域进行排序

    1. enum SortCriterion
    2. {
    3. FIRST_POINT, //区域第一行的最左侧的点
    4. LAST_POINT, //区域最后一行的最右侧的点
    5. UPPER_LEFT, //区域周围矩形的左上角
    6. UPPER_RIGHT, //区域周围矩形的右上角
    7. LOWER_LEFT, //区域周围矩形的左下角
    8. LOWER_RIGHT //区域周围矩形的右下角
    9. };
    10. enum SortDirection
    11. {
    12. ROW, //区域按行排列,即从左到右,从上到下
    13. COLUMN //区域按列排列,即从上到下,从左到右
    14. };
    15. //功能:由区域的相对位置对区域进行排序
    16. //参数:
    17. // src:输入图像
    18. // contours:输入图像中的轮廓组
    19. // pos:已排序的轮廓索引
    20. // sc:排序基准点
    21. // isDue:
    22. // true:从小到大进行排序
    23. // false:从大到小进行排序
    24. // sd:排序方向
    25. //返回值:true:排序成功
    26. // false:排序失败
    27. bool sort_region(Mat src,vector<vector<Point>> contours, vector<int> &pos,
    28. SortCriterion sc, bool isDue, SortDirection sd)
    29. {
    30. int count = contours.size();
    31. pos.resize(count);
    32. vector<Point> points;
    33. for (int i = 0; i < count; i++)
    34. {
    35. pos[i] = i;
    36. Rect rect = boundingRect(contours[i]);
    37. if (sc == FIRST_POINT)
    38. {
    39. int row = rect.y;
    40. for (int col = rect.x; col <= rect.x + rect.width; col++)
    41. {
    42. if (src.at<uchar>(row, col) > 0)
    43. {
    44. points.push_back(Point(col, row));
    45. break;
    46. }
    47. }
    48. }
    49. else if (sc == LAST_POINT)
    50. {
    51. int row = rect.y + rect.height;
    52. for (int col = rect.x + rect.width; col >= rect.x; col--)
    53. {
    54. if (src.at<uchar>(row, col) > 0)
    55. {
    56. points.push_back(Point(col, row));
    57. break;
    58. }
    59. }
    60. }
    61. else if (sc == UPPER_LEFT)
    62. points.push_back(rect.tl());
    63. else if (sc == UPPER_RIGHT)
    64. points.push_back(Point(rect.x + rect.width, rect.y));
    65. else if (sc == LOWER_LEFT)
    66. points.push_back(Point(rect.x, rect.y + rect.height));
    67. else if (sc == LOWER_RIGHT)
    68. points.push_back(rect.br());
    69. }
    70. int np = points.size();
    71. if (np != count)
    72. return false;
    73. if (sd == ROW)
    74. {
    75. for (int i = 0; i < count - 1; i++)
    76. {
    77. for (int j = 0; j < count - 1 - i; j++)
    78. {
    79. if (isDue)
    80. {
    81. if (points[j].y > points[j + 1].y)
    82. {
    83. Point temp = points[j];
    84. points[j] = points[j + 1];
    85. points[j + 1] = temp;
    86. int index = pos[j];
    87. pos[j] = pos[j + 1];
    88. pos[j + 1] = index;
    89. }
    90. }
    91. else
    92. {
    93. if (points[j].y < points[j + 1].y)
    94. {
    95. Point temp = points[j];
    96. points[j] = points[j + 1];
    97. points[j + 1] = temp;
    98. int index = pos[j];
    99. pos[j] = pos[j + 1];
    100. pos[j + 1] = index;
    101. }
    102. }
    103. }
    104. }
    105. for (int i = 0; i < count - 1; i++)
    106. {
    107. for (int j = 0; j < count - 1 - i; j++)
    108. {
    109. if (points[j].y == points[j + 1].y)
    110. {
    111. if (isDue)
    112. {
    113. if (points[j].x > points[j + 1].x)
    114. {
    115. Point temp = points[j];
    116. points[j] = points[j + 1];
    117. points[j + 1] = temp;
    118. int index = pos[j];
    119. pos[j] = pos[j + 1];
    120. pos[j + 1] = index;
    121. }
    122. }
    123. else
    124. {
    125. if (points[j].x < points[j + 1].x)
    126. {
    127. Point temp = points[j];
    128. points[j] = points[j + 1];
    129. points[j + 1] = temp;
    130. int index = pos[j];
    131. pos[j] = pos[j + 1];
    132. pos[j + 1] = index;
    133. }
    134. }
    135. }
    136. }
    137. }
    138. }
    139. else if (sd == COLUMN)
    140. {
    141. for (int i = 0; i < count - 1; i++)
    142. {
    143. for (int j = 0; j < count - 1 - i; j++)
    144. {
    145. if (isDue)
    146. {
    147. if (points[j].x > points[j + 1].x)
    148. {
    149. Point temp = points[j];
    150. points[j] = points[j + 1];
    151. points[j + 1] = temp;
    152. int index = pos[j];
    153. pos[j] = pos[j + 1];
    154. pos[j + 1] = index;
    155. }
    156. }
    157. else
    158. {
    159. if (points[j].x < points[j + 1].x)
    160. {
    161. Point temp = points[j];
    162. points[j] = points[j + 1];
    163. points[j + 1] = temp;
    164. int index = pos[j];
    165. pos[j] = pos[j + 1];
    166. pos[j + 1] = index;
    167. }
    168. }
    169. }
    170. }
    171. for (int i = 0; i < count - 1; i++)
    172. {
    173. for (int j = 0; j < count - 1 - i; j++)
    174. {
    175. if (points[j].x == points[j + 1].x)
    176. {
    177. if (isDue)
    178. {
    179. if (points[j].y > points[j + 1].y)
    180. {
    181. Point temp = points[j];
    182. points[j] = points[j + 1];
    183. points[j + 1] = temp;
    184. int index = pos[j];
    185. pos[j] = pos[j + 1];
    186. pos[j + 1] = index;
    187. }
    188. }
    189. else
    190. {
    191. if (points[j].y < points[j + 1].y)
    192. {
    193. Point temp = points[j];
    194. points[j] = points[j + 1];
    195. points[j + 1] = temp;
    196. int index = pos[j];
    197. pos[j] = pos[j + 1];
    198. pos[j + 1] = index;
    199. }
    200. }
    201. }
    202. }
    203. }
    204. }
    205. return true;
    206. }

    8.shape_trans()区域转换算子

    1. enum ShapeTransType
    2. {
    3. SHAPETRANS_RECTANGLE, //平行于坐标轴的最小外接矩形
    4. SHAPETRANS_CIRCLE, //最小外接圆
    5. SHAPETRANS_CONVER //凸包
    6. };
    7. //功能:变换区域的形状
    8. //参数:
    9. // src:输入图像
    10. // dst:输出图像
    11. // type:变换形状
    12. //返回值:无
    13. void shape_trans(Mat src, Mat &dst, ShapeTransType type)
    14. {
    15. dst = Mat(src.size(), CV_8UC1, Scalar(0));
    16. vector<vector<Point>> contours;
    17. findContours(src, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    18. int n = contours.size();
    19. for (int i = 0; i < n; i++)
    20. {
    21. if (type == SHAPETRANS_RECTANGLE)
    22. {
    23. Rect rect = boundingRect(contours[i]);
    24. rectangle (dst, rect, Scalar(255), CV_FILLED);
    25. }
    26. else if (type == SHAPETRANS_CIRCLE)
    27. {
    28. Point2f center;
    29. float radius;
    30. minEnclosingCircle(contours[i], center, radius);
    31. circle (dst, center, radius, Scalar(255), CV_FILLED);
    32. }
    33. else if (type == SHAPETRANS_CONVER)
    34. {
    35. vector<Point> conver;
    36. convexHull(contours[i], conver);
    37. vector<vector<Point>> pconver;
    38. pconver.push_back(conver);
    39. fillPoly(dst, pconver, Scalar(255));
    40. }
    41. }
    42. }

    9.opencv双阈值二值化---->Halcon的直方图双阈值二值化

    halcon算子:

                    threshold(img , region , 40 , 160 )

    1. //正向阈值二值化与反向阈值二值化按位与操作取交集
    2. Mat src= imread("1.png");
    3. Mat m1, m2, dst;
    4. threshold(src, m1, 40, 255, cv::THRESH_BINARY);
    5. threshold(src, m2, 160, 255, cv::THRESH_BINARY_INV);
    6. bitwise_and(m1, m2, dst);
    1. void Threshold(cv::Mat &src, cv::Mat &dst, int lowThresh, int highThresh)
    2. {
    3. if(src.empty())
    4. {
    5. std::cout<<"src is empty"<<std::endl;
    6. return;
    7. }
    8. dst = cv::Mat::zeros(src.size(), src.type());
    9. double t = (double)cv::getTickCount();
    10. for(int i = 0; i < src.rows; i++)
    11. {
    12. uchar *srcPt = (uchar*)src.data + i * src.step;
    13. uchar *dstPt = (uchar*)dst.data + i * dst.step;
    14. for(int j = 0; j < src.cols; j++)
    15. {
    16. uchar pixel = *srcPt++;
    17. if(pixel > lowThresh && pixel < highThresh)
    18. *dstPt = 255;
    19. dstPt++;
    20. }
    21. }
    22. t = ((double)cv::getTickCount() - t) / cv::getTickFrequency()*1000; //获得时间,单位是毫秒
    23. cout <<"耗时:"<< t<<"ms"<<endl;
    24. }

     10.Gray_range_rect()图像灰度增强预处理

    1. //halcon gray_range_rect算子的C++实现
    2. void gray_range_rect(Mat &src, Mat &dst, Size size)
    3. {
    4. //图像边界扩充
    5. int hh = (size.height - 1) / 2;
    6. int hw = (size.width - 1) / 2;
    7. cv::Mat Newsrc;
    8. cv::copyMakeBorder(src, Newsrc, hh, hh, hw, hw, cv::BORDER_REFLECT_101);//以边缘为轴,对称
    9. dst = cv::Mat::zeros(src.rows, src.cols, src.type());
    10. //遍历图像
    11. for (int i = 0; i < src.rows; i++)
    12. {
    13. for (int j = 0; j < src.cols; j++)
    14. {
    15. //uchar srcValue = src.at<uchar>(i, j);
    16. int minValue = 255;
    17. int maxValue = 0;
    18. for (int k = 0; k < hh; k++)
    19. {
    20. for (int z = 0; z < hw; z++)
    21. {
    22. int srcValue = (int)Newsrc.at<uchar>(i + k, j + z);
    23. minValue = minValue > srcValue ? srcValue : minValue;
    24. maxValue = maxValue > srcValue ? maxValue : srcValue;
    25. }
    26. }
    27. uchar diffValue = (uchar)(maxValue - minValue);
    28. dst.at<uchar>(i, j) = diffValue;
    29. }
    30. }
    31. }

    后续学习更新。。

  • 相关阅读:
    智能家居项目开发准备工作
    Windows 本地安装 Mysql8.0
    自学系列之小游戏---贪吃蛇(vue3+ts+vite+element-plus+sass)(module.scss + tsx)
    2022年了你还不了解箭头函数与普通函数的区别吗?
    《向量数据库》——都有哪些向量数据库,都有什么特点?
    springmvc3:ajax请求,文件上传下载,拦截器,异常处理,注解配置mvc
    奢侈品鉴定机构小程序开发制作功能介绍
    软考 系统架构设计师 简明教程 | 系统设计
    9、MySQL——表与表之间的关系,多表查询、MySQL数据库的备份与恢复
    Android 蓝牙设备类型判断代码介绍
  • 原文地址:https://blog.csdn.net/weixin_50016546/article/details/125465347