【图像处理】-002 图像灰度线性变换

图像灰度线性变换

文章目录

  • 1 概念
  • 2 原理
  • 3 作用
  • 4 Matlab实现
  • 5 OpenCV实现
  • 6 效果图
  • 6.1 效果图
  • 7 讨论

1 概念

  灰度线性变换是一种灰度变换,通过建立灰度映射来调整源图像的灰度,达到图像增强的目的。灰度映射通常使用灰度变换曲线来表示。

2 原理

  灰度线性变换就是将图像的像素值通过指定的线性函数进行变换,以此增强或减弱图像的灰度。灰度线性变换的公式是常见的一维线性函数:
g ( x , y ) = k ⋅ f ( x , y ) + b g(x,y) = k \cdot f(x,y) + b g(x,y)=kf(x,y)+b
x x x为原始灰度值,则变换后的灰度值 y y y为:
y = k ⋅ x + b … … ( 0 ≤ y ≤ 255 ) y = k \cdot x + b \dots\dots(0 \leq y \leq 255) y=kx+b(0y255)
k k k表示直线的斜率,即倾斜程度, b b b表示线性函数在 y y y轴的截距。

3 作用

  

k k k b b b取值 意义
k > 1 k>1 k>1 增大图像的对比度,图像的像素值在变换后全部增大,整体效果被增强
k = 1 k=1 k=1 通过调整 b b b,实现对图像亮度的调整
0 < k < 1 0 < k < 1 0<k<1 图像的对比度被削弱
k < 0 k<0 k<0 原来图像亮的区域变暗,原来图像暗的区域变亮

4 Matlab实现

clc;
clear;
close all;

% 对灰度图进行灰度线性变换
ori_img = imread('../images/6.jpg');
ori_img = rgb2gray(ori_img);
[oriHist,oriX] = imhist(ori_img);

k = 1.25;
d = 0;
gray1 = ori_img * k + d;
[g1Hist,g1X] = imhist(gray1);

k = 1;
d = 50;
gray2 = ori_img * k + d;
[g2Hist,g2X] = imhist(gray2);

k = 0.5;
d = 0;
gray3 = ori_img * k + d;
[g3Hist,g3X] = imhist(gray3);

k = -1;
d = 255;
ori_ = im2double(ori_img);
gray4 = ori_ * k + 1.0;
[g4Hist,g4X] = imhist(gray4);

figure(1),subplot(1,2,1),imshow(ori_img),title('原图');subplot(1,2,2),imshow(gray1),title('k>0 d=0');
figure(2),subplot(1,2,1),stem(oriX,oriHist),title('原图直方图');subplot(1,2,2),stem(g1X,g1Hist),title('k>0 d=0直方图');
figure(3),subplot(1,2,1),imshow(ori_img),title('原图');subplot(1,2,2),imshow(gray2),title('k=1 d=50');
figure(4),subplot(1,2,1),stem(oriX,oriHist),title('原图直方图');subplot(1,2,2),stem(g2X,g2Hist),title('k=1 d=50直方图');
figure(5),subplot(1,2,1),imshow(ori_img),title('原图');subplot(1,2,2),imshow(gray3),title('k=0.5 d=0');
figure(6),subplot(1,2,1),stem(oriX,oriHist),title('原图直方图');subplot(1,2,2),stem(g3X,g3Hist),title('k=0.5 d=0直方图');
figure(7),subplot(1,2,1),imshow(ori_img),title('原图');subplot(1,2,2),imshow(gray4),title('k=-1 d=255');
figure(8),subplot(1,2,1),stem(oriX,oriHist),title('原图直方图');subplot(1,2,2),stem(g4X,g4Hist),title('k=-1 d=255直方图');

5 OpenCV实现

#include 
#include 

#include "../include/opencv400/opencv2/opencv.hpp"
#include "windows.h"

std::string g_CurrentDirectory;
void SetCurrentDirectoryToExePath()
{
	HMODULE hExe = GetModuleHandleA(NULL);
	char nameBuf[MAX_PATH] = { 0 };
	GetModuleFileNameA(hExe, nameBuf, MAX_PATH);
	std::string sName(nameBuf);
	sName = sName.substr(0, sName.rfind('\\'));
	SetCurrentDirectoryA(sName.c_str());
	g_CurrentDirectory = sName;
}


void calcHist1D(cv::Mat& input, cv::Mat& output)
{
	int channels[] = { 0 };
	int histsize[] = { 256 };
	float grayRnage[] = { 0,256 };
	const float* ranges[] = { grayRnage };
	cv::MatND hist;
	cv::calcHist(&input, 1, channels, cv::Mat(), hist, 1, histsize, ranges);

	double maxVal = 0;
	cv::minMaxLoc(hist, 0, &maxVal, 0, 0);

	int scale = 10;
	output = cv::Mat::zeros(500, 257 * 5, CV_8UC3);

	std::cout << "-----------------------------------" << std::endl;
	for (int i = 0; i < histsize[0]; i++)
	{
		float binVal = hist.at(i, 0);
		std::cout <

6 效果图

原图
【图像处理】-002 图像灰度线性变换_第1张图片

6.1 效果图

k> 1 b=0
【图像处理】-002 图像灰度线性变换_第2张图片【图像处理】-002 图像灰度线性变换_第3张图片【图像处理】-002 图像灰度线性变换_第4张图片
【图像处理】-002 图像灰度线性变换_第5张图片【图像处理】-002 图像灰度线性变换_第6张图片

7 讨论

线性变换是一个有限的查表操作,在C++实现时可以在将图像逐像素的计算过程转换为查表操作。由于灰度线性变换的查找表只需256字节,完全可以全部缓存到现代CPU的cache中,通过多线程的查表操作,可以加快整个图像的变换过程。当然,这样速度还是没有GPU中进行速度快。灰度线性变换是与相邻像素无关的操作,非常适合在GPU中并行计算。但需要根据图像大小,考虑图像从CPU到GPU再从GPU到CPU的时间损耗,时间加快只对很大的图有效。

你可能感兴趣的:(图像处理,图像处理)