混合空间增强法(基于OpenCV的C++实现)
2018-02-08 09:23
543 查看
下面我们对一幅人体骨骼扫描图进行混合空间增强。之前在网上找了很多关于空间增强的代码,但是都只有matlab的版本,一直没有找到C++的版本。所以我结合冈萨雷斯的《数字图像处理》上面的思路,粗略的写了一个C++的版本。整个算法的框架如下:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void toBeOne(Mat &input, Mat &output, int index = 0)
{
float max = 0, min = 0;
output = Mat::zeros(input.rows, input.cols, CV_8UC3);
for (int i = 0; i<input.rows; i++)
{
float *ptr = input.ptr<float>(i);
for (int j = 0; j<input.cols * 3; j++)//图像为3通道
{
if (max<ptr[j])
max = ptr[j];
if (min>ptr[j])
min = ptr[j];
}
}
//取出图像中的上下限
for (int i = 0; i<input.rows; i++)
{
float *ptr = input.ptr<float>(i);
uchar *optr = output.ptr<uchar>(i);
for (int j = 0; j<input.cols * 3; j++)
{
if (index){
if (ptr[j]>1){
optr[j] = 255;
continue;
}
else if (ptr[j]<0){
optr[j] = 0;
continue;
}
else
optr[j] = (uchar)(ptr[j] * 255);
}
else
optr[j] = (uchar)((ptr[j] - min) / (max - min) * 255);
}
}
}
//γ变换
cv::Mat gammaTran(const cv::Mat src, double gamma, double comp)
{
cv::Mat dst(src);
int M = 0;
int N = 0;
if (src.empty()){
std::cout << "Src pic is empty" << std::endl;
return src;
}
M = src.rows;
N = src.cols*src.channels();
for (int i = 0; i < M; i++){
const float *p1 = src.ptr<const float>(i);
float *p2 = dst.ptr<float>(i);
for (int j = 0; j < N; j++){
p2[j] = pow(p1[j], gamma) * comp;
}
}
return dst;
}
int main()
{
Mat iinput = imread("C:/Users/53148/Desktop/body1.png"), input, Tlaplas;
imshow("original", iinput);
iinput.convertTo(input, CV_32F, 1.0 / 255, 0);//把图片转化为float类型,这样子可以直接进行加减而不会溢出
//Laplacian变换
Mat kern = (Mat_<char>(3, 3) << 1, 1, 1, //滤波器
1, -8, 1,
1, 1, 1);
Mat laplas;
Mat output;
filter2D(input, laplas, input.depth(), kern);//使用滤波器kern对input进行相关操作,结果存储在laplas中
toBeOne(laplas, Tlaplas);
imshow("Tlaplas", Tlaplas);
output = input - laplas;//如果中间的值是正的则是加号,负值则是减号
toBeOne(output, iinput, 1);
Mat R0 = iinput;
imshow("laplace", R0);
//Sobel梯度
Mat kern2 = (Mat_<char>(3, 3) << -1, -2, -1,
0, 0, 0,
1, 2, 1);
Mat kern3 = (Mat_<char>(3, 3) << -1, 0, 1,
-2, 0, 2,
-1, 0, 1);
Mat gx, gy;
filter2D(input, gx, input.depth(), kern2);
filter2D(input, gy, input.depth(), kern3);
Mat Soutput = abs(gx) + abs(gy);
toBeOne(Soutput, iinput, 1);
Mat R1 = iinput;
imshow("Sobel1", R1);
//盒滤波器平滑
Mat smooth;
blur(iinput, smooth, Size(5, 5));
Mat R2 = smooth;
imshow("Smooth", R2);
//相乘
Mat R3, r3;
R0.convertTo(R0, CV_32F, 1.0 / 255, 0);
R2.convertTo(R2, CV_32F, 1.0 / 255, 0);
multiply(R0, R2, r3);
toBeOne(r3, R3, 1);
imshow("Result0",R3);
//锐化增强
cv::Mat r4, R4;
r4 = input + r3;
toBeOne(r4, R4, 1);
imshow("Result1", R4);
//γ变换
cv::Mat r5, R5;
r5 = gammaTran(r4, 0.5, 1);
toBeOne(r5, R5, 1);
imshow("Result", R5);
waitKey();
return 0;
}
通过增强的效果图如下:
以上仅仅是我学习过程中的笔记,如有什么疏漏,敬请指正!
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void toBeOne(Mat &input, Mat &output, int index = 0)
{
float max = 0, min = 0;
output = Mat::zeros(input.rows, input.cols, CV_8UC3);
for (int i = 0; i<input.rows; i++)
{
float *ptr = input.ptr<float>(i);
for (int j = 0; j<input.cols * 3; j++)//图像为3通道
{
if (max<ptr[j])
max = ptr[j];
if (min>ptr[j])
min = ptr[j];
}
}
//取出图像中的上下限
for (int i = 0; i<input.rows; i++)
{
float *ptr = input.ptr<float>(i);
uchar *optr = output.ptr<uchar>(i);
for (int j = 0; j<input.cols * 3; j++)
{
if (index){
if (ptr[j]>1){
optr[j] = 255;
continue;
}
else if (ptr[j]<0){
optr[j] = 0;
continue;
}
else
optr[j] = (uchar)(ptr[j] * 255);
}
else
optr[j] = (uchar)((ptr[j] - min) / (max - min) * 255);
}
}
}
//γ变换
cv::Mat gammaTran(const cv::Mat src, double gamma, double comp)
{
cv::Mat dst(src);
int M = 0;
int N = 0;
if (src.empty()){
std::cout << "Src pic is empty" << std::endl;
return src;
}
M = src.rows;
N = src.cols*src.channels();
for (int i = 0; i < M; i++){
const float *p1 = src.ptr<const float>(i);
float *p2 = dst.ptr<float>(i);
for (int j = 0; j < N; j++){
p2[j] = pow(p1[j], gamma) * comp;
}
}
return dst;
}
int main()
{
Mat iinput = imread("C:/Users/53148/Desktop/body1.png"), input, Tlaplas;
imshow("original", iinput);
iinput.convertTo(input, CV_32F, 1.0 / 255, 0);//把图片转化为float类型,这样子可以直接进行加减而不会溢出
//Laplacian变换
Mat kern = (Mat_<char>(3, 3) << 1, 1, 1, //滤波器
1, -8, 1,
1, 1, 1);
Mat laplas;
Mat output;
filter2D(input, laplas, input.depth(), kern);//使用滤波器kern对input进行相关操作,结果存储在laplas中
toBeOne(laplas, Tlaplas);
imshow("Tlaplas", Tlaplas);
output = input - laplas;//如果中间的值是正的则是加号,负值则是减号
toBeOne(output, iinput, 1);
Mat R0 = iinput;
imshow("laplace", R0);
//Sobel梯度
Mat kern2 = (Mat_<char>(3, 3) << -1, -2, -1,
0, 0, 0,
1, 2, 1);
Mat kern3 = (Mat_<char>(3, 3) << -1, 0, 1,
-2, 0, 2,
-1, 0, 1);
Mat gx, gy;
filter2D(input, gx, input.depth(), kern2);
filter2D(input, gy, input.depth(), kern3);
Mat Soutput = abs(gx) + abs(gy);
toBeOne(Soutput, iinput, 1);
Mat R1 = iinput;
imshow("Sobel1", R1);
//盒滤波器平滑
Mat smooth;
blur(iinput, smooth, Size(5, 5));
Mat R2 = smooth;
imshow("Smooth", R2);
//相乘
Mat R3, r3;
R0.convertTo(R0, CV_32F, 1.0 / 255, 0);
R2.convertTo(R2, CV_32F, 1.0 / 255, 0);
multiply(R0, R2, r3);
toBeOne(r3, R3, 1);
imshow("Result0",R3);
//锐化增强
cv::Mat r4, R4;
r4 = input + r3;
toBeOne(r4, R4, 1);
imshow("Result1", R4);
//γ变换
cv::Mat r5, R5;
r5 = gammaTran(r4, 0.5, 1);
toBeOne(r5, R5, 1);
imshow("Result", R5);
waitKey();
return 0;
}
通过增强的效果图如下:
以上仅仅是我学习过程中的笔记,如有什么疏漏,敬请指正!
相关文章推荐
- 基于Opencv2.4.11+OpenGL(Qt5.6.0)实现增强现实(二)
- 直方图均衡化的 C++ 实现(基于 openCV)
- 连通区域标记:c++版的bwlabel实现(基于opencv)
- 基于Opencv2.4.11+OpenGL(Qt5.6.0)实现增强现实(四)
- SIFT特征2-基于OpenCV和C++的算法实现
- DCT变换及量化的c++实现(基于opencv矩阵运算)
- C++基于OpenCV实现实时监控和运动检测记录
- OpenCV图像处理 空间域图像增强(图像锐化 1 基于拉普拉斯算子)
- 基于Opencv2.4.11+OpenGL(Qt5.6.0)实现增强现实(一)
- 图像卷积操作的手动实现(基于opencv的C++编译环境)
- 基于OpenCV的RGB和HSV色彩空间相互转换C++程序
- opencv中的GMM(混合高斯分布)算法原理及C++实现(BackgroundSubtractorMOG)
- 基于VS C++平台的OpenCV设置,实现简单的行人检测
- 基于Opencv2.4.11+OpenGL(Qt5.6.0)实现增强现实(五)
- LLC(Locality-constrained Linear Coding)基于OpenCV的C++源码实现
- 基于OpenCV的RGB和HSV色彩空间相互转换C++程序
- 【算法+OpenCV】基于三次Bezier原理的曲线拟合算法C++与OpenCV实现
- 基于OpenCV的人脸检测——C++和Python实现
- 基于OpenCV和C++实现最大阈值分割算法
- 匈牙利算法的C++实现(基于OpenCV)