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

文章介绍了如何使用OpenCV实现类似于Halcon的动态阈值算法,包括两种不同的实现方案,并展示了图像锐化增强处理的方法。此外,还讨论了基于OpenCV的区域填充、计算区域面积与中心坐标、对区域进行排序以及形状转换等图像处理技术。
摘要由CSDN通过智能技术生成

目录

1.Dyn_threshold 动态阈值

 2.OpenCV实现

2.Emphasize图像锐化增强处理

5.Fill_up()区域填充算子

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

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

8.shape_trans()区域转换算子

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

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


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

 3.select_shape()特征筛选

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值