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