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

图像灰度非线性变换

1 原理

  图像灰度的非线性变换主要有对数变换、指数变换、幂次变换等。本文主要讨论对数变换。

  对数变换的基本形式如下:
y = log ⁡ ( 1 + x ) b y=\frac{\log{(1+x)}}{b} y=blog(1+x)
其中, b b b为正常数,用以控制曲线的弯曲程度。

  对数变换实现了图像灰度扩展和压缩的功能,它扩展低灰度值而压缩高灰度值。

2 Matlab实现

clc;
clear;
close all;

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

k = 1.25;
d = 0;
gray1 = log(1+ori_img) /0.065;
gray1(find(gray1>255))=255;
gray1=uint8(gray1);
[g1Hist,g1X] = imhist(gray1);


figure(1),subplot(1,2,1),imshow(ori_img1),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直方图');

3 OpenCV实现

3.1 实现

#include <iostream>
#include <string>

#include "../include/opencv400/opencv2/opencv.hpp"
#include "../include/opencv400/opencv2/core.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<float>(i, 0);
		//std::cout << i << " " << binVal << std::endl;
		int intensity = cvRound(binVal * 500 / maxVal);
		rectangle(output, cv::Point(i * 5, 500 - intensity),
			cv::Point((i + 1) * 5, 500),
			cv::Scalar::all(255),
			-1);
	}

}

int main()
{
	SetCurrentDirectoryToExePath();

	cv::Mat ori_img = cv::imread("../images/6.jpg");
	cv::Mat gray_img;
	cv::cvtColor(ori_img, gray_img, cv::COLOR_BGR2GRAY);
	cv::namedWindow("灰度图");
	cv::imshow("灰度图", gray_img);

	cv::Mat grayHist;
	calcHist1D(gray_img, grayHist);
	cv::imshow("hist", grayHist);

	gray_img.convertTo(gray_img, CV_32FC1, 1.0 );

	cv::Mat g1;
	cv::log(1 + gray_img,g1);
	g1 = g1 / 0.025;

	cv::Mat m255(gray_img.rows, gray_img.cols, CV_32FC1);
	m255 = cv::Scalar(255);
#undef min
	cv::min(g1, m255, g1);
	g1.convertTo(g1, CV_8UC1);
	cv::Mat g1Hist;
	calcHist1D(g1, g1Hist);
	cv::imshow("g1Hist", g1Hist);
	imshow("dd", g1);

	

	cv::waitKey();
	return 0;
}

3.2 注意

  OpenCV中提供了对cv::Matlog,sqrt,min,max等操作,在core.hpp文件中。使用min函数可以实现对Mat中各元素超过阈值进行截断的功能。
例如,在上述实现中,对g1超过255的值进行截断,赋值为255.通过以下代码实现。

	cv::Mat m255(gray_img.rows, gray_img.cols, CV_32FC1);
	m255 = cv::Scalar(255);
#undef min
	cv::min(g1, m255, g1);

注意其中的#undef min,由于定义了宏min,导致在调用cv::min函数的时候会编译错误。

4 效果图

在这里插入图片描述在这里插入图片描述

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值