OpenCV在C++下的练习

1.颜色通道转换
#include <opencv2/core.hpp>
#include <opencv2/highgui/highgui.hpp>

void show_pic(cv::String winname, cv::Mat mat);

int main(int argc, char* argv[])
{
	cv::Mat img = imread("test.jpg", cv::IMREAD_COLOR);

	int width = img.rows;
	int height = img.cols;

	cv::Mat out = img.clone();
	show_pic("original", out);

	for (int i = 0; i < height; ++i)
	{
		for (int j = 0; j < width; ++j)
		{
			unsigned char tmp = out.at<cv::Vec3b>(j, i)[0];
			out.at<cv::Vec3b>(j, i)[0] = img.at<cv::Vec3b>(j, i)[2];
			out.at<cv::Vec3b>(j, i)[2] = tmp;
		}
	}
	show_pic("changed", out);

	return 0;
}


void show_pic(cv::String winname, cv::Mat mat)
{
	cv::imshow(winname, mat);
	cv::waitKey(0);
	cv::destroyAllWindows();
}


2.图像灰度化

预定义类型的结构如下所示:

CV_<bit_depth>(S|U|F)C<number_of_channels>

  • 1–bit_depth—比特数—代表8bite,16bites,32bites,64bites
    举个例子吧–比如说,如果你现在创建了一个存储–灰度图片的Mat对象,这个图像的大小为宽100,高100,那么,现在这张灰度图片中有10000个像素点,它每一个像素点在内存空间所占的空间大小是8bite,8位–所以它对应的就是CV_8
  • 2–S|U|F–S–代表—signed int—有符号整形
    U–代表–unsigned int–无符号整形
    F–代表–float---------单精度浮点型
  • 3–C<number_of_channels>----代表—一张图片的通道数,比如:
    1–灰度图片–grayImg—是–单通道图像
    2–RGB彩色图像---------是–3通道图像
    3–带Alph通道的RGB图像–是–4通道图像

灰度化的方法:

  • 分量法
  • 最大值法
  • 平均值法
  • 加权平均法(Y = 0.2126 R + 0.7152 G + 0.0722 B)
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;

/*
 * Y = 0.2126 R + 0.7152 G + 0.0722 B
 */

int main(int argc, const char* argv[]) {
	cv::Mat img = cv::imread("test.jpg", cv::IMREAD_COLOR);

	int width = img.rows;
	int height = img.cols;


	Mat out = Mat::zeros(width, height, CV_8UC1);

	for (int i = 0; i < out.rows; i++)
	{
		for (int j = 0; j < out.cols; j++)
		{
			out.at<uchar>(i, j) = float(img.at<Vec3b>(i, j)[0] * 0.0722) +
				float(img.at<Vec3b>(i, j)[1] * 0.7152) +
				float(img.at<Vec3b>(i, j)[2] * 0.2126);
		}
	}

	cv::imshow("answer", out);
	cv::waitKey(0);
	cv::destroyAllWindows();
	system("pause");

	return 0;

}

注意at(函数中的类型区别)
在这里插入图片描述

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

int main(int argc, char* argv[])
{
	Mat img = imread("C:\\Users\\MSI-NB\\Desktop\\test1.jpg", cv::IMREAD_COLOR);
	// unsigned char r_c = img.at<uchar>(1, 1);
	std::cout << "unchar:"<< int(img.at<uchar>(2, 2))<< endl;
	std::cout << "Vec3b:"<<img.at<Vec3b>(2, 2)<< endl;

	system("pause");
}

3.大津二值化算法

参考链接一
参考链接二

otsu 大津算法是一种图像二值化算法,作用是确定将图像分成黑白两个部分的阈值。

方差越大,相关性越低,黑白越分明。

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

void show_pic(cv::String winname, cv::Mat mat);

int main(int argc, char* argv[])
{
	//导入图像
	Mat img = imread("test.jpg", IMREAD_COLOR);

	int width = img.rows;
	int height = img.cols;

	//定义0图
	Mat gray = Mat::zeros(width, height, CV_8UC1);

	show_pic("original_gray", gray);

	//灰度化
	for (int i = 0; i < width; ++i)
	{
		for (int j = 0; j < height; ++j)
		{
			gray.at<uchar>(i, j) = float(img.at<Vec3b>(i, j)[0] * 0.0722) + float(img.at<Vec3b>(i, j)[1] * 0.7152) + float(img.at<Vec3b>(i, j)[2] * 0.2126);
		}

	}

	show_pic("gray", gray);

	//阈值确定
	double w0 = 0, w1 = 0;
	double m0 = 0, m1 = 0;
	double max_sb = 0, sb = 0;

	int th = 0;

	int val = 0;

	for (int t = 0; t < 255; ++t)
	{
		w0 = 0;
		w1 = 0;
		m0 = 0;
		m1 = 0;
		for (int i = 0; i < width; ++i)
		{
			for (int j = 0; j < height; ++j)
			{
				val = gray.at<uchar>(i, j);
				if (val < t)
				{
					w0++;
					m0 += val;
				}
				else
				{
					w1++;
					m1 += val;
				}
			}


		}

		m0 /= w0;
		m1 /= w1;

		w0 /= (height*width);
		w1 /= (height*width);
		sb = w0*w1*pow((m0 - m1), 2);

		if (sb > max_sb)
		{
			max_sb = sb;
			th = t;
		}
	}

	for (int i = 0; i < width; ++i)
	{
		for (int j = 0; j < height; ++j)
		{
			val = gray.at<uchar>(i, j);
			if (val < th)
			{
				val = 0;
			}
			else
			{
				val = 255;
			}
			gray.at<uchar>(i, j) = val;
		}
	}

	show_pic("Otsu", gray);

	system("pause");
	return 0;

}




4.二值化
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

void show_pic(cv::String winname, cv::Mat mat);

int main(int argc, char* argv[])
{
	Mat img = imread("test.jpg", IMREAD_COLOR);

	int width = img.rows;
	int height = img.cols;
	int th = 128;

	Mat gray = Mat::zeros(width, height, CV_8UC1);

	show_pic("gray", gray);

	for (int i = 0; i < width; ++i)
	{
		for (int j = 0; j < height; ++j)
		{
			unsigned char tmp = img.at<Vec3b>(i, j)[0] * 0.0722 + img.at<Vec3b>(i, j)[0] * 0.7152 + img.at<Vec3b>(i, j)[2] * 0.2126;

			if (tmp<128)
			{
				gray.at<uchar>(i, j) = 0;
			}else
			{
				gray.at<uchar>(i, j) = 255;
			}
		}
	}

	show_pic("threhold", gray);

	return 0;
}


5.HSV变换

HSV 变换就是HSV色彩和RGB色彩之间可以互相转换。

HSV 即使用色相(Hue)、饱和度(Saturation)、明度(Value)来表示色彩的一种方式。


6.减色处理
val = {  32  (  0 <= val <  64)
         96  ( 64 <= val < 128)
        160  (128 <= val < 192)
        224  (192 <= val < 256)
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>

using namespace std;
using namespace cv;

void show_pic(cv::String winname, cv::Mat mat);

int main(int argc, char* argv[])
{
	Mat img = imread("test.jpg", IMREAD_COLOR);
	int width = img.rows;
	int height = img.cols;

	Mat out = Mat::zeros(width, height, CV_8UC3);

	for (int i = 0; i < width; ++i)
	{
		for (int j = 0; j < height; ++j)
		{
			for (int c = 0; c < 3; ++c)
			{
				out.at<Vec3b>(i, j)[c] = floor((double)img.at<cv::Vec3b>(i, j)[c] / 64) * 64 + 32;
			}
		}
	}
	show_pic("out", out);
	system("pause");
	return 0;
}


7.均值池化
#include <imgproc.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

void show_pic(cv::String winname, cv::Mat mat);

int main(int argc, char* argv[])
{
	Mat img = imread("test.jpg", IMREAD_COLOR);
	show_pic("img", img);

	int width = img.rows;
	int height = img.cols;

	int stride = 8;
	double v = 0;

	if (width%stride != 0 || height%stride != 0)
	{
		width += (width%stride);
		height += (height%stride);

	}

	// Size size = Size(width, height);
	Size size = Size(height, width);
	resize(img, img, size);
	show_pic("img", img);

	Mat out = Mat::zeros(width, height, CV_8UC3);
	show_pic("out", out);

	for (int i = 0; i < width; i += stride)
	{
		for (int j = 0; j < height; j += stride)
		{
			for (int c = 0; c < 3; ++c)
			{
				v = 0;
				for (int _i = 0; _i < stride; ++_i)
				{
					for (int _j = 0; _j < stride; ++_j)
					{
						v += img.at<Vec3b>(i + _i, j + _j)[c];
					}
				}
				v /= (stride*stride);
				// std::cout << v << endl;
				for (int _i = 0; _i < stride; ++_i)
				{
					for (int _j = 0; _j < stride; ++_j)
					{
						out.at<Vec3b>(i + _i, j + _j)[c] = v;
					}
				}
			}
		}
	}

	show_pic("out", out);

	// for (int i = 0; i < width - stride; i += stride)
	// {
	// 	for (int j = 0; j < height - stride; j += stride)
	// 	{
	// 		for (int c = 0; c < 3; ++c)
	// 		{
	// 			v = 0;
	// 			for (int _i = 0; _i < stride; ++_i)
	// 			{
	// 				for (int _j = 0; _j < stride; ++_j)
	// 				{
	// 					v += img.at<Vec3b>(i + _i, j + _j)[c];
	// 				}
	// 			}
	// 			v /= (stride*stride);
	// 			// std::cout << v << endl;
	// 			for (int _i = 0; _i < stride; ++_i)
	// 			{
	// 				for (int _j = 0; _j < stride; ++_j)
	// 				{
	// 					out.at<Vec3b>(i + _i, j + _j)[c] = v;
	// 				}
	// 			}
	// 		}
	// 	}
	// }
	//
	// show_pic("out", out);

}


8.最大池化
#include <imgproc.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

void show_pic(cv::String winname, cv::Mat mat);

int main8(int argc, char* argv[])
{
	Mat img = imread("test.jpg", IMREAD_COLOR);
	show_pic("img", img);

	int width = img.rows;
	int height = img.cols;

	int stride = 8;
	double v = 0;

	if (width%stride != 0 || height%stride != 0)
	{
		width += (width%stride);
		height += (height%stride);

	}

	Size size = Size(height, width); //h,w
	resize(img, img, size);
	show_pic("img", img);

	Mat out = Mat::zeros(width, height, CV_8UC3);
	show_pic("out", out);

	for (int i = 0; i < width; i += stride)
	{
		for (int j = 0; j < height; j += stride)
		{
			for (int c = 0; c < 3; ++c)
			{
				v = 0;
				for (int _i = 0; _i < stride; ++_i)
				{
					for (int _j = 0; _j < stride; ++_j)
					{
						v = img.at<Vec3b>(i + _i, j + _j)[c] > v ? img.at<Vec3b>(i + _i, j + _j)[c] : v;
					}
				}
				for (int _i = 0; _i < stride; ++_i)
				{
					for (int _j = 0; _j < stride; ++_j)
					{
						out.at<Vec3b>(i + _i, j + _j)[c] = v;
					}
				}
			}
		}
	}
	show_pic("out", out);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值