基于opencv的灰度变换
不同灰度变换只是使用的公式不同而已,核心思想都是在空间域直接对每一个像素的灰度值进行判断处理,代码很简单。
//基本灰度变换
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
#define CUTTING_LOW 0
//查看像素值
void View(Mat src)
{
ofstream PView;
PView.open("PView.txt");
int num = 0;
for (int i = 0;i < src.rows;i++)
{
for (int j = 0;j < src.cols;j++)
{
if (num == 50)
{
num = 0;
PView << endl;
}
else
{
int a = src.at
PView << a << " ";
num++;
}
}
}
PView.close();
}
//图像反转
void Reverse(Mat src,Mat intermediate)
{
for (int i = 0;i < src.rows;i++)
{
for (int j = 0;j < src.cols;j++)
{
intermediate.at
}
}
}
#e#
//对数变换
void Log(Mat src, Mat intermediate,int c)
{
for (int i = 0;i < src.rows;i++)
{
for (int j = 0;j < src.cols;j++)
{
int b = c*log(1+src.at
int d = b % 256;
intermediate.at
}
}
}
//幂次变换
void Power(Mat src, Mat intermediate,float gamma)
{
for (int i = 0;i < src.rows;i++)
{
for (int j = 0;j < src.cols;j++)
{
float c = pow(255, 1 - gamma);
int b = c*pow(src.at
int d = b % 256;
intermediate.at
}
}
}
//对比拉伸
void Stretch(Mat src, Mat intermediate,float r1, float s1, float r2, float s2 )
{
float k1, k2, k3, b1, b2, b3;
k1 = s1 / r1;
b1 = 0.0;
k2 = (s2 - s1) / (r2 - r1);
b2 = (s1*r2 - s2*r1) / (r2 - r1);
k3 = (255.0 - s2) / (255.0 - r2);
b3 = (255.0*s2-r2*255.0) / (255.0 - r2);
cout << b3;
for (int i = 0;i < src.rows;i++)
{
for (int j = 0;j < src.cols;j++)
{
if (src.at
{
int a = k1*src.at
int b = a % 256;
intermediate.at
}
if (src.at
{
int a = k2*src.at
int b = a % 256;
intermediate.at
}
if (src.at
{
int a = k3*src.at
int b = a % 256;
intermediate.at
}
}
}
}
#e#
//灰度切割
void Cutting(Mat src, Mat intermediate, float r1,float r2,int type,int low,int high)
{
if (type == CUTTING_MAINTAIN)
{
for (int i = 0;i < src.rows;i++)
{
for (int j = 0;j < src.cols;j++)
{
if (src.at
{
intermediate.at
}
if (src.at
{
intermediate.at
}
if (src.at
{
intermediate.at
}
}
}
}
else
{
for (int i = 0;i < src.rows;i++)
{
for (int j = 0;j < src.cols;j++)
{
if (src.at
{
intermediate.at
}
if (src.at
{
intermediate.at
}
if (src.at
{
intermediate.at
}
}
}
}
}
int main()
{
Mat src = cv::imread("Spectrum.tif", 0),temp;
Mat intermediate(src.rows, src.cols, CV_8UC1);
//cv::resize(src, temp, Size(src.cols*0.6, src.rows*0.6));
cv::imshow("Source", src);
//View(src);
Reverse(src, intermediate);
//Log(src, intermediate,45);
//Power(src, intermediate, 0.8);
//Stretch(src, intermediate,32.0,96.0,160.0,224.0);
//Cutting(src, intermediate, 50.0, 100.0,CUTTING_MAINTAIN,0,255);
//cv::resize(intermediate, intermediate, Size(intermediate.cols*0.6, intermediate.rows*0.6));
cv::imshow("intermediate", intermediate);
cv::imwrite("D:\\Computer Software\\Visual Studio 2015\\Projects\\ImageProcessing\\ImageProcessing\\检测结果Spectrum-Reverse.tif", intermediate);
cv::waitKey(0);
return 0;
}
代码里处理的图片都是《数字图像处理》的源图像,第二版的好像不再出版了,只找到了第三版的源图像,不过差不太多的。
附部分检测结果的图片:
1.幂次变换用于增强对比度:
源图像:
幂次变换(γ=0.4):
2.灰度切割:
源图像:
增强[50,100]区间灰度值为255,其余灰度值保持不变:
增强[50,100]区间灰度值为255,其余灰度值变化为0:
改进一下:
实现鼠标交互操作:使用鼠标圈出矩形框,只对矩形框内像素进行处理,可以更直观的观察某种算法对图像产生的变化。下面以对比拉伸为例:
#include
#include
#include
#include
using namespace std;
using namespace cv;
Rect rect;
bool rect_flag = false;
//获取鼠标所选取的矩形
void onMouse(int event,int x,int y,int flags,void*param)
{
if (event == CV_EVENT_LBUTTONDOWN)
{
rect.x = x;
rect.y = y;
rect_flag = false;
}
if (event == CV_EVENT_LBUTTONUP)
{
rect.width = x - rect.x;
rect.height = y - rect.y;
rect_flag = true;
}
}
//对比拉伸
void Stretch(Mat src, Mat intermediate,float r1, float s1, float r2, float s2 )
{
float k1, k2, k3, b1, b2, b3;
k1 = s1 / r1;
b1 = 0.0;
k2 = (s2 - s1) / (r2 - r1);
b2 = (s1*r2 - s2*r1) / (r2 - r1);
k3 = (255.0 - s2) / (255.0 - r2);
b3 = (255.0*s2-r2*255.0) / (255.0 - r2);
for (int i = rect.y;i < rect.y+rect.height;i++)
{
for (int j = rect.x;j < rect.x+rect.width;j++)
{
if (src.at
{
int a = k1*src.at
int b = a % 256;
intermediate.at
}
if (src.at
{
int a = k2*src.at
int b = a % 256;
intermediate.at
}
if (src.at
{
int a = k3*src.at
int b = a % 256;
intermediate.at
}
}
}
}
int main()
{
Mat src = cv::imread("Pollen.tif", 0),temp, intermediate;
cv::resize(src, temp, Size(src.cols*0.6, src.rows*0.6));
cv::imshow("Source", temp);
namedWindow("intermediate",1);
setMouseCallback("intermediate", onMouse, 0);
while (1)
{
cv::resize(src, intermediate, Size(src.cols*0.6, src.rows*0.6));
//消除第一次画矩形后第二次点击鼠标直接在点击位置画出与上一个矩形等大矩形的情况
if (rect_flag)
{
Stretch(temp, intermediate, 100.0, 1.0, 120.0, 254.0);
cv::rectangle(intermediate, rect, Scalar(255, 0, 0), 1);
}
cv::imshow("intermediate", intermediate);
//ESC按键
char c = (char)waitKey(20);
if (27 == c)
return -1;
}
return 0;
}
效果图
评论
查看更多