目录
官方在线帮助文档:OpenCV: OpenCV modules
官方在线帮助文档:OpenCV: OpenCV modules
用OpenCV对图像做一些简单的操作
1. 图像直方图
图像直方图的解释
图像直方图是图像像素值的统计学特征、计算代价较小,具有图像平移、旋转、缩放不变性等众多优点,
广泛地应用于图像处理的各个领域,特别是灰度图像的阈值分割、基于颜色的图像检索以及图像分类、反向投影跟踪。
常见的分为
- 灰度直方图
- 颜色直方图
Bins是指直方图的大小范围,对于像素值取值在0~255之间的,最少有256个bin,此外还可以有16、32、48、128等,256除以bin的大小应该是整数倍。
OpenCV中相关API
calcHist(&bgr_plane[0],1,0,Mat(), b_hist,1, bins,ranges);
cv.calcHist([image],[i],None,[256],[0,256])
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace cv;
using namespace std;
class demo
{
public:
// 图像直方图
void histogram_demo(Mat& image) {
// 三通道分离
vector<Mat> bgr_plane;
split(image, bgr_plane);
// 定义参数变量
const int channels[1] = { 0 };
const int bins[1] = { 256 };
float hranges[2] = { 0,255 };
const float* ranges[1] = { hranges };
Mat b_hist;
Mat g_hist;
Mat r_hist;
//计算Blue, Green,Red通道的直方图
calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges);
calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);
//显示直方图
int hist_w = 512;
int hist_h = 400;
int bin_w = cvRound((double)hist_w / bins[0]);
Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
//归一化直方图数据
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
// 绘制直方图曲线
for (int i = 1; i < bins[0]; i++) {
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
Point(bin_w * (i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
Point(bin_w * (i), hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, 8, 0);
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
Point(bin_w * (i), hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, 8, 0);
}
// 显示直方图
namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
imshow("Histogram Deno", histImage);
}
};
int main(int argc, char** argv)
{
Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
// namedWindow("输出窗口", WINDOW_FREERATIO);
// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
if (src.empty()) {
cout << "没有找到你的图片" << endl;
return -1;
}
imshow("输出窗口", src);
demo d;
d.histogram_demo(src);
waitKey(0);// 设置图片显示时间
destroyAllWindows();// 释放所有窗口
return 0;
}
2. 图像二维直方图
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace cv;
using namespace std;
class demo
{
public:
// 二维直方图
void histogram_2d_demo(Mat& image)
{
// 2D直方图
Mat hsv, hs_hist;
cvtColor(image, hsv, COLOR_BGR2HSV);
int hbins = 30, sbins = 32;
int hist_bins[] = { hbins, sbins };
float h_range[] = { 0,180 };
float s_range[] = { 0,256 };
const float* hs_ranges[] = { h_range, s_range };
int hs_channels[] = { 0,1 };
calcHist(&hsv,1, hs_channels,Mat(), hs_hist,2, hist_bins, hs_ranges, true, false);
double maxval = 0;
minMaxLoc(hs_hist, 0, &maxval, 0, 0);
int scale = 10;
Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3);
for (int h = 0; h < hbins; h++) {
for (int s = 0; s < sbins; s++) {
float binVal = hs_hist.at<float>(h, s);
int intensity = cvRound(binVal * 255 / maxval);
rectangle(hist2d_image, Point(h * scale, s * scale),
Point((h + 1) * scale - 1, (s + 1) * scale - 1),
Scalar::all(intensity),
-1);
}
// 输出图像色彩转换
applyColorMap(hist2d_image, hist2d_image, COLORMAP_JET);
imshow("H-S Histogram", hist2d_image);
// imwrite("D:/ hist__2d.png", hist2d_image);
}
}
};
int main(int argc, char** argv)
{
Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
// namedWindow("输出窗口", WINDOW_FREERATIO);
// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
if (src.empty()) {
cout << "没有找到你的图片" << endl;
return -1;
}
imshow("输出窗口", src);
demo d;
d.histogram_2d_demo(src);
waitKey(0);// 设置图片显示时间
destroyAllWindows();// 释放所有窗口
return 0;
}
3. 图像直方图均衡化
图像直方图均衡化
图像直方图均衡化可以用于图像增强、对输入图像进行直方图均衡化处理,提升后续对象检测的准确率在OpenCV人脸检测的代码演示中已经很常见。此外对医学影像图像与卫星遥感图像也经常通过直方图均衡化来提升图像质量。
API
- equalizeHist(src,dst)
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace cv;
using namespace std;
class demo
{
public:
// 直方图均衡化
void histogram_eq_demo(Mat& image)
{
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("灰度图像", gray);
Mat dst;
equalizeHist(gray, dst);
imshow("图像直方图均衡化演示", dst);
}
};
int main(int argc, char** argv)
{
Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
// namedWindow("输出窗口", WINDOW_FREERATIO);
// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
if (src.empty()) {
cout << "没有找到你的图片" << endl;
return -1;
}
imshow("输出窗口", src);
demo d;
d.histogram_eq_demo(src);
waitKey(0);// 设置图片显示时间
destroyAllWindows();// 释放所有窗口
return 0;
}
4. 图像卷积操作
相关API (C++)
- blur(
InputArray src, //输入
OutputArray dst, //输出
Size ksize, //窗口大小
Point anchor = Point(-1,-1), //默认值
int borderType = BORDER_ _DEFAULT //默认值)
Python版本
dst= cv.blur( src, ksize[, dst[, anchor[, borderTyel]] )
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace cv;
using namespace std;
class demo
{
public:
// 图像卷积操作
void blur_demo(Mat& image)
{
Mat dst;
blur(image, dst, Size(23,23), Point(-1, -1));
// 支持一维卷积---->Size(15,1)
imshow("图像模糊", dst);
}
};
int main(int argc, char** argv)
{
Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
// namedWindow("输出窗口", WINDOW_FREERATIO);
// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
if (src.empty()) {
cout << "没有找到你的图片" << endl;
return -1;
}
imshow("输出窗口", src);
demo d;
d.blur_demo(src);
waitKey(0);// 设置图片显示时间
destroyAllWindows();// 释放所有窗口
return 0;
}
5. 高斯模糊
图像均值与高斯模糊
均值模糊是卷积核的系数完全一致,高斯模糊考虑了中心像素距离的影响,对距离中心像素使用高斯分布公式生成不同的权重系数给卷积核,然后用此卷积核完成图像卷积得到输出结果就是图像高斯模糊之后的输出。
OpenCV高斯模糊API函数
void GaussianBlur(
InputArray src,
OutputArray dst,
Size ksize, // Ksize为高斯滤波器窗口大小
double sigmax, //X方向滤波系数
double sigmaY=O, // Y方向滤波系数
int borderType=BORDER_DEFAULT //默认边缘插值方法 )
当Size(0,0)就会从sigmax开始计算生成高斯卷积核系数,当时size不为零是优先从size开始计算高斯卷积核系数
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace cv;
using namespace std;
class demo
{
public:
// 高斯模糊
void gaussian_blur_demo(Mat& image)
{
Mat dst;
GaussianBlur(image, dst, Size(0, 0), 15);
// Size(0, 0)是最厉害的模糊
imshow("高斯模糊图像", dst);
}
};
int main(int argc, char** argv)
{
Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
// namedWindow("输出窗口", WINDOW_FREERATIO);
// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
if (src.empty()) {
cout << "没有找到你的图片" << endl;
return -1;
}
imshow("输出窗口", src);
demo d;
d.gaussian_blur_demo(src);
waitKey(0);// 设置图片显示时间
destroyAllWindows();// 释放所有窗口
return 0;
}
6. 高斯双边模糊(边缘滤波)
边缘保留滤波算法–高斯双边模糊
前面我们介绍的图像卷积处理无论是均值还是高斯都是属于模糊卷积,它们都有一个共同的特点就是模糊之后图像的边缘信息不复存在,
受到了破坏。我们今天介绍的滤波方法有能力通过卷积处理实现图像模糊的同时对图像边缘不会造成破坏,滤波之后的输出完整的保存了图像整体边缘(轮廓)信息,我们称这类滤波算法为边缘保留滤波算法(EPF)。最常见的边缘保留滤波算法有以下几种
高斯双边模糊
Meanshift均值迁移模糊局部均方差模糊
OpenCV中对边缘保留滤波还有一个专门的API
高斯模糊是考虑图像空间位置对权重的影响,但是它没有考虑图像像素分布对图像卷积输出的影响,双边模糊考虑了像素值分布的影响,对像素值空间分布差异较大的进行保留从而完整的保留了图像的边缘信息。
C++:
bilateralFilter(
InputArray src,
OutputArray dst,
int d,
double sigmaColor,
double sigmaSpace,
int borderType = BORDER_DEFAULT
)
Python:
dst =cv.bilateralFilter(src,d, sigmaColor, sigmaSpace[, dst[,borderType]] )
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace cv;
using namespace std;
class demo
{
public:
// 高斯双边模糊
void bifilter_demo(Mat& image)
{
// 磨皮美颜
Mat dst;
bilateralFilter(image, dst, 0, 100, 10);
imshow("双边模糊", dst);
}
};
int main(int argc, char** argv)
{
Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
// namedWindow("输出窗口", WINDOW_FREERATIO);
// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
if (src.empty()) {
cout << "没有找到你的图片" << endl;
return -1;
}
imshow("输出窗口", src);
demo d;
d.bifilter_demo(src);
waitKey(0);// 设置图片显示时间
destroyAllWindows();// 释放所有窗口
return 0;
}