OpenCV实现基本灰度变换
来源:互联网 发布:华为软件官网 编辑:程序博客网 时间:2024/06/07 01:32
OpenCV小白一枚,最近在看数字图像处理第二版,看课本的同时想加深一下理解,自己动手写一些代码实现一下课本中的效果。
看到第三章了,实现一些基本灰度变换的效果。不同灰度变换只是使用的公式不同而已,核心思想都是在空间域直接对每一个像素的灰度值进行判断处理,代码很简单。
//基本灰度变换#include<iostream>#include<cmath>#include<fstream>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>using namespace std;using namespace cv;#define CUTTING_MAINTAIN 1#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<uchar>(i, j); 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<uchar>(i, j) = 255 - src.at<uchar>(i, j); } }}//对数变换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<uchar>(i, j)); int d = b % 256; intermediate.at<uchar>(i, j) = d; } }}//幂次变换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<uchar>(i, j), gamma); int d = b % 256; intermediate.at<uchar>(i, j) = d; } }}//对比拉伸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<uchar>(i, j) >= 0.0 && src.at<uchar>(i, j) <= r1) { int a = k1*src.at<uchar>(i, j) + b1; int b = a % 256; intermediate.at<uchar>(i, j) = b; } if (src.at<uchar>(i, j) >= r1 && src.at<uchar>(i, j) <= r2) { int a = k2*src.at<uchar>(i, j) + b2; int b = a % 256; intermediate.at<uchar>(i, j) = b; } if (src.at<uchar>(i, j) >= r2 && src.at<uchar>(i, j) <= 255.0) { int a = k3*src.at<uchar>(i, j) + b3; int b = a % 256; intermediate.at<uchar>(i, j) = b; } } }}//灰度切割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<uchar>(i, j) >= 0.0 && src.at<uchar>(i, j) <= r1) { intermediate.at<uchar>(i, j) = src.at<uchar>(i, j); } if (src.at<uchar>(i, j) >= r1 && src.at<uchar>(i, j) <= r2) { intermediate.at<uchar>(i, j) = high; } if (src.at<uchar>(i, j) >= r2 && src.at<uchar>(i, j) <= 255.0) { intermediate.at<uchar>(i, j) = src.at<uchar>(i, j); } } } } else { for (int i = 0;i < src.rows;i++) { for (int j = 0;j < src.cols;j++) { if (src.at<uchar>(i, j) >= 0.0 && src.at<uchar>(i, j) <= r1) { intermediate.at<uchar>(i, j) = low; } if (src.at<uchar>(i, j) >= r1 && src.at<uchar>(i, j) <= r2) { intermediate.at<uchar>(i, j) = high; } if (src.at<uchar>(i, j) >= r2 && src.at<uchar>(i, j) <= 255.0) { intermediate.at<uchar>(i, j) = low; } } } }}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<iostream>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/core/core.hpp>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<uchar>(i, j) >= 0.0 && src.at<uchar>(i, j) <= r1) { int a = k1*src.at<uchar>(i, j) + b1; int b = a % 256; intermediate.at<uchar>(i, j) = b; } if (src.at<uchar>(i, j) >= r1 && src.at<uchar>(i, j) <= r2) { int a = k2*src.at<uchar>(i, j) + b2; int b = a % 256; intermediate.at<uchar>(i, j) = b; } if (src.at<uchar>(i, j) >= r2 && src.at<uchar>(i, j) <= 255.0) { int a = k3*src.at<uchar>(i, j) + b3; int b = a % 256; intermediate.at<uchar>(i, j) = b; } } }}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;}
效果图
0 0
- OpenCV实现基本灰度变换
- opencv实现对数log灰度变换
- 灰度图像的对数变换原理及OpenCV代码实现!
- 基本的灰度变换方法
- 图像灰度变换及实现
- 图像灰度变换及实现
- OpenCV常用的灰度变换方法
- OpenCV简单图像处理 灰度变换
- 利用Opencv进行图像灰度变换处理
- 数字图像处理基本算法实现(1)--section3.2基本灰度变换
- opencv的灰度变换使用及与自己实现的效果比较
- 数字图像的基本灰度变换函数
- 图像基本变换---图像灰度化
- 灰度变换
- 灰度变换
- opencv:图像的基本变换
- opencv python 4 基本变换
- Opencv学习手册(四)--- 图像灰度变换
- LeetCode:Odd Even Linked List
- Spring Cloud——断路器监控Hystrix Dashboard&Turbine
- ubuntu改变区域后对Postgresql的影响
- matlab常用快捷键
- pat 1120. Friend Numbers
- OpenCV实现基本灰度变换
- the diary for redirection in linux
- java设计模式--组合
- doGet与doPost的区别
- MySql分区类型以及建分区语句
- 南阳理工ACM 题目57 6174问题
- Jedis客户端操作redis
- 不同的路径 II
- AVL树自平衡的几种旋转