目录

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 动态阈值

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

2.OpenCV实现

方案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;}}
}

2.Emphasize图像锐化增强处理

  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的值会被置为255optr[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);}}}
}

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:

#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();
}

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

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);
}

5.Fill_up()区域填充算子

//功能:填充区域中的孔洞
//参数:
//  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);
}

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

//功能:求图中像素值为255的斑块面积和重心坐标
//参数:
//  src:输入图像
//  area:图中像素值为255的像素个数
//  center:斑块的重心坐标
//返回值:无
void area_center(Mat src, int &area, Point2f &center)
{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);}
}

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


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;
}

8.shape_trans()区域转换算子


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));}}
}

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

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;
}

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

//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;}}
}

后续学习更新。。

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

  1. halcon区域腐蚀膨胀算子_超越halcon速度的二值图像的腐蚀和膨胀,实现目前最快的半径相关类算法(附核心源码)。...

    超越halcon速度的二值图像的腐蚀和膨胀,实现目前最快的半径相关类算法(附核心源码). 发布时间:2019-03-20 12:32, 浏览次数:1259 , 标签: halcon 我在两年前的博客里 ...

  2. 【youcans 的 OpenCV 例程200篇】127. 形态算法之细化

    欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中 欢迎关注 『youcans 的 OpenCV学习课』 系列,持续更新中 [youcans 的 OpenCV 例程 2 ...

  3. 【youcans 的 OpenCV 例程200篇】125. 形态算法之提取连通分量

    欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中 欢迎关注 『youcans 的 OpenCV学习课』 系列,持续更新中 [youcans 的 OpenCV 例程 2 ...

  4. 使用OpenCV进行人脸识别的三种算法(官方网翻译)

    怎样使用OpenCV进行人脸识别 本文大部分来自OpenCV官网上的Face Reconition with OpenCV这节内容(http://docs.opencv.org/modules/con ...

  5. 【youcans 的 OpenCV 例程200篇】128. 形态算法之骨架 (skimage)

    欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中 欢迎关注 『youcans 的 OpenCV学习课』 系列,持续更新中 [youcans 的 OpenCV 例程20 ...

  6. 【youcans 的 OpenCV 例程200篇】129. 形态算法之骨架 (重建开运算)

    欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中 欢迎关注 『youcans 的 OpenCV学习课』 系列,持续更新中 [youcans 的 OpenCV 例程20 ...

  7. 【youcans 的 OpenCV 例程200篇】123. 形态算法之孔洞填充

    欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中 欢迎关注 『youcans 的 OpenCV学习课』 系列,持续更新中 [youcans 的 OpenCV 例程 2 ...

  8. 【OpenCV图像处理入门学习教程六】基于Python的网络爬虫与OpenCV扩展库中的人脸识别算法比较

    OpenCV图像处理入门学习教程系列,上一篇第五篇:基于背景差分法的视频目标运动侦测 一.网络爬虫简介(Python3) 网络爬虫,大家应该不陌生了.接下来援引一些Jack-Cui在专栏<Pyt ...

  9. 基于OpenCV的电影视频人像景别分类算法(源码&教程)

    1.研究背景 近年来,随着多媒体技术的高速发展,视频数据也呈现出爆炸性的增长.基于内容的视频检索已成为当前的迫切需求.特别在电影视频领域,单纯的播放已经无法满足用户日益增长的需要.如何准确快速地按照用 ...

最新文章

  1. 推荐给程序员的书:七月图书推荐
  2. python 3读取文件-Python3 yaml文件读写操作
  3. (转) oc static extern 和const
  4. 通过Dapr实现一个简单的基于.net的微服务电商系统(十一)——一步一步教你如何撸Dapr之自动扩/缩容...
  5. 从实现原理来讲,Nacos 为什么这么强
  6. Python多种方法实现句子中单词倒置(好未来2017笔试题)
  7. break;continue语句
  8. 经典的HTML5游戏及其源码分析
  9. 【PCIe 协议】听说你做 PCIe 很多年,还不知道 PCIe Hierarchy ID 是什么 ???
  10. 中国移动光猫获取超级密码教程
  11. 坐标拾取器功能实现demo
  12. iphone页面怎么实现固定工具栏 html css js,固定工具栏 data-position=fixed
  13. [JZOJ5199]Fiend
  14. 【论文制图】chemdraw安装与使用
  15. JS实现图结构封装,使用邻接表实现(广度优先搜索,深度优先搜索)
  16. (转载)一次Linux系统被攻击的分析过程
  17. MATLAB和EXCEL交互 Spreadsheet Link
  18. tp link拨号失败 服务器无响应,pppoe拨号失败解决方法_pppoe怎么设置
  19. 使用Google语音识别引擎(Google Speech API)
  20. 1.22-1.23板卡调试日志

热门文章

  1. 第365章 布局于墓_神墓_辰东_玄幻小说
  2. 《Windows办公指南》01:电脑篇
  3. 5.10.2_动画计时器
  4. DataV基础版如何制作单独省份地图?
  5. CPU和SoC的关系和区别
  6. php获取正文中所有图片
  7. IO流丶序列化与反序列化
  8. Git回滚文件常用命令汇总
  9. 高德地图行业领头,企业网盘为其发展保驾护航
  10. #HTML5网页中的文本与图像