C++ Opencv——图像处理(实时更新)

目录

图像增强

图像增强——RGB图分离并均衡化 

图像增强——RGB图分离并对数log变换

图像增强——滤波器

图像增强——高反差

图像增强——边缘增强

形态学——膨胀

图像分割

图像分割——OTSU阈值

图像分割——Kmeans

图像滤波

多种滤波器

 


图像增强

图像增强——RGB图分离并均衡化 

Mat src = imread(argv[i]);
Mat imageRGB[3];
split(src, imageRGB);
for (int i = 0; i < 3; i++)
{
	equalizeHist(imageRGB[i], imageRGB[i]);
}
merge(imageRGB, 3, src);

图像增强——RGB图分离并对数log变换

Mat image = imread(argv[i]);
Mat imageLog(image.size(), CV_32FC3);
for (int i = 0; i < image.rows; i++)
{
    for (int j = 0; j < image.cols; j++)
    {
        imageLog.at<Vec3f>(i, j)[0] = log(1 + image.at<Vec3b>(i, j)[0]);
        imageLog.at<Vec3f>(i, j)[1] = log(1 + image.at<Vec3b>(i, j)[1]);
        imageLog.at<Vec3f>(i, j)[2] = log(1 + image.at<Vec3b>(i, j)[2]);
    }
}
//归一化到0~255  
normalize(imageLog, imageLog, 0, 255, CV_MINMAX);
//转换成8bit图像显示  
convertScaleAbs(imageLog, imageLog);

图像增强——滤波器

// 滤波器
void sharpenImage(const cv::Mat &image, cv::Mat &result)
{
	//创建并初始化滤波模板
	/*滤波核为拉普拉斯核3x3:
	0 -1 0
	-1 5 -1
	0 -1 0
	*/
	cv::Mat kernel(3, 3, CV_32F, cv::Scalar(0));
	kernel.at<float>(0, 1) = -1.0;
	kernel.at<float>(1, 0) = -1.0;
	kernel.at<float>(1, 1) = 5.0;	
	kernel.at<float>(1, 2) = -1.0;
	kernel.at<float>(2, 1) = -1.0;

	result.create(image.size(), image.type());

	//对图像进行滤波
	cv::filter2D(image, result, image.depth(), kernel);
}

图像增强——高反差

Mat HighPass(Mat img)
{
	Mat temp;
	GaussianBlur(img, temp, Size(7, 7), 1.6, 1.6);

	int r = 3;
	Mat diff = img + r*(img - temp); //高反差保留算法
	return diff;
}

图像增强——边缘增强

void edgeEnhance(cv::Mat& srcImg, cv::Mat& dstImg)
{
	if (!dstImg.empty())
	{
		dstImg.release();
	}

	std::vector<cv::Mat> rgb;

	if (srcImg.channels() == 3)        // rgb image
	{
		cv::split(srcImg, rgb);
	}
	else if (srcImg.channels() == 1)   // gray image
	{
		rgb.push_back(srcImg);
	}

	// 分别对R、G、B三个通道进行边缘增强
	for (size_t i = 0; i < rgb.size(); i++)
	{
		cv::Mat sharpMat8U;
		cv::Mat sharpMat;
		cv::Mat blurMat;

		// 高斯平滑
		cv::GaussianBlur(rgb[i], blurMat, cv::Size(3, 3), 0, 0);

		// 计算拉普拉斯
		cv::Laplacian(blurMat, sharpMat, CV_16S);

		// 转换类型
		sharpMat.convertTo(sharpMat8U, CV_8U);
		cv::add(rgb[i], sharpMat8U, rgb[i]);
	}


	cv::merge(rgb, dstImg);
}

形态学——膨胀

图像分割

图像分割——OTSU阈值

//otsu阈值自动求取
double getThreshVal_Otsu(const cv::Mat& _src)
{
	cv::Size size = _src.size();
	if (_src.isContinuous())
	{
		size.width *= size.height;
		size.height = 1;
	}
	const int N = 256;
	int i, j, h[N] = { 0 };
	for (i = 0; i < size.height; i++)
	{
		const uchar* src = _src.data + _src.step*i;
		for (j = 0; j <= size.width - 4; j += 4)
		{
			int v0 = src[j], v1 = src[j + 1];
			h[v0]++; h[v1]++;
			v0 = src[j + 2]; v1 = src[j + 3];
			h[v0]++; h[v1]++;
		}
		for (; j < size.width; j++)
			h[src[j]]++;
	}

	double mu = 0, scale = 1. / (size.width*size.height);
	for (i = 0; i < N; i++)
		mu += i*h[i];

	mu *= scale;
	double mu1 = 0, q1 = 0;
	double max_sigma = 0, max_val = 0;

	for (i = 0; i < N; i++)
	{
		double p_i, q2, mu2, sigma;

		p_i = h[i] * scale;
		mu1 *= q1;
		q1 += p_i;
		q2 = 1. - q1;

		if (std::min(q1, q2) < FLT_EPSILON || std::max(q1, q2) > 1. - FLT_EPSILON)
			continue;

		mu1 = (mu1 + i*p_i) / q1;
		mu2 = (mu - q1*mu1) / q2;
		sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2);
		if (sigma > max_sigma)
		{
			max_sigma = sigma;
			max_val = i;
		}
	}

	return max_val;
}

图像分割——Kmeans

Mat Image_Kmeans(Mat src, int n)
{
	int width = src.cols;
	int height = src.rows;
	int dims = src.channels();

	// 初始化定义 
	int sampleCount = width*height;
	int clusterCount = n;//分几类
	Mat points(sampleCount, dims, CV_32F, Scalar(10));
	Mat labels;
	Mat centers(clusterCount, 1, points.type());

	// 图像RGB到数据集转换 
	int index = 0;
	for (int row = 0; row < height; row++) {
		for (int col = 0; col < width; col++) {
			index = row*width + col;
			Vec3b rgb = src.at<Vec3b>(row, col);
			points.at<float>(index, 0) = static_cast<int>(rgb[0]);
			points.at<float>(index, 1) = static_cast<int>(rgb[1]);
			points.at<float>(index, 2) = static_cast<int>(rgb[2]);
		}
	}

	// 运行K-Means数据分类 
	TermCriteria criteria = TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0);
	kmeans(points, clusterCount, labels, criteria, 3, KMEANS_PP_CENTERS, centers);

	// 显示图像分割结果 
	Mat result = Mat::zeros(src.size(), CV_8UC3);
	for (int row = 0; row < height; row++) {
		for (int col = 0; col < width; col++) {
			index = row*width + col;
			int label = labels.at<int>(index, 0);
			if (label == 1) {
				result.at<Vec3b>(row, col)[0] = 255;
				result.at<Vec3b>(row, col)[1] = 0;
				result.at<Vec3b>(row, col)[2] = 0;
			}
			else if (label == 2){
				result.at<Vec3b>(row, col)[0] = 0;
				result.at<Vec3b>(row, col)[1] = 255;
				result.at<Vec3b>(row, col)[2] = 0;
			}
			else if (label == 3) {
				result.at<Vec3b>(row, col)[0] = 0;
				result.at<Vec3b>(row, col)[1] = 0;
				result.at<Vec3b>(row, col)[2] = 255;
			}
			else if (label == 0) {
				result.at<Vec3b>(row, col)[0] = 0;
				result.at<Vec3b>(row, col)[1] = 255;
				result.at<Vec3b>(row, col)[2] = 255;
			}
		}
	}
	return result;
}

图像滤波

多种滤波器

https://blog.csdn.net/zoucharming/article/details/70197863

在图像处理中,尽可能消除图片中的噪声,消除噪声就需要用到滤波,在本次opencv学习中,学习了三个滤波方式。

(1)平均滤波,就是将一个区域内的像素值求和取平均值,然后用这个平均值替换区域中心的像素值。

blur(源Mat对象,目标Mat对象,Size对象,Point对象)//Size对象用来确定区域大小,Point对象如果x,y都是-1则表示更新区域中心的像素。

(2)高斯滤波,也是将一个区域的像素值求取平均值替换区域中心的像素值,但是是加权平均,权重按照二维正态分布。

GaussianBlur(源Mat对象,目标Mat对象,Size对象,x方向正太分布参数,y方向正太分布参数)

(3)中值滤波,之前的两个滤波都有个问题,如果区域中有极端值,很可能影响滤波效果,中值滤波采用区域中的中值来替换,有利于克服椒盐噪声。

medianBlur(源Mat对象,目标Mat对象,int size)//这里的size表示正方形区域的边长

(4)双边滤波,之前的滤波还有个问题,他们都会把轮廓给模糊了,有一些区域之间相差较大的像素,这往往能看出轮廓,所以如果我们给个限制范围,如果两点间的像素值差距大于这个范围就不滤波了,保留图像轮廓

bilateralFilter(源Mat对象,目标Mat对象,int 区域半径,int 限制范围,int space)//space是当区域半径给的是0时,用来计算区域范围的,一般情况下没用,随便给个数就行。

#include<opencv2\opencv.hpp>
#include<iostream>
#include<math.h>
#include<algorithm>
 
using namespace std;
using namespace cv;
 
int main()
{
	Mat src;
	src = imread("1.jpg", 1);
	if (src.empty())
	{
		printf("cannot load!!\n");
		return -1;
	}
	namedWindow("原图");
	imshow("原图", src);
	Mat dst,dst1;
	blur(src, dst, Size(3, 3), Point(-1, -1));
	namedWindow("均值滤波");
	imshow("均值滤波", dst);
	GaussianBlur(src, dst, Size(5, 5), 5, 5);
	namedWindow("高斯滤波");
	imshow("高斯滤波", dst);
	medianBlur(src, dst, 5);
	namedWindow("中值滤波");
	imshow("中值滤波", dst);
	bilateralFilter(src, dst, 5, 100, 3);
	namedWindow("双边滤波");
	imshow("双边滤波", dst);
 
	waitKey(0);
 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41275726/article/details/84799766