图像对比度的计算和代码实现

618 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情

首先,需要了解一下什么是图像的对比度,我们看一张图像时经常会觉得有的图像清晰一些,而有的图像不是很清晰,这就引出了图像对比度的概念,图像对比度在一定程度上体现了图像亮暗的拉伸对比程度。

对于图像对比对的计算公式,表示如下,其中第二行的公式表示像素差,这个像素差可以是4邻域相邻,也可以是8邻域相邻.第三行公式表示的是相邻像素间的灰度差为delta 的像素分布概率。

image.png

下面通过一个例子进行说明,下面就表示一个3x3像素大小的图像矩阵,以四邻域为例子进行说明,图像的对比度如何计算。

   1  3   5
   2  4   4
   5  7   4
   

C=[(1^2+2^2) + (1^2+(-2)^2)+2^2) + ((-1)^2+(-2)^2) + ((-1)^2+3^2+2^2) + ((-1)^2+3^2+(-2)^2+0^2) + (1^2+0^2+0^2) + ((-3)^2+2^2) + ((-3)^2+(-2)^2) + (0^2+3^2)]/24=3.08

对于上面的计算流程,以左上角的1来说,它的四邻域分别是上下左右四个方向,但是1的位置在最边上,因此只有下和右两个邻域,分别是2和3,将两个邻域分别与1做差,然后求平方值,就完成了一个计算,对上面所有的像素执行这样的操作将结果相加,然后除以总的计算数的个数,就得到了这个3x3区域的对比度。

以代码进行表示如下,代码是C++编写的,使用了opencv框架,代码我准备编译为动态链接库的形式提供给外部调用,因此在每个函数的前面加上了__declspec(dllexport) 。

// 这一句为调用头文件,因为新建项目的时候我选择的新建DLL项目,如果建的空项目,这个头文件可以不要
#include"pch.h"

#include<iostream>
#include <opencv2/opencv.hpp>

using namespace cv;

__declspec(dllexport) double contrast(Mat image)
{
	Mat image_gray;
	cv::cvtColor(image, image_gray, cv::COLOR_BGR2GRAY);
	int m = image.rows;
	int n = image.cols;

	Mat image_ext;
	cv::copyMakeBorder(image_gray, image_ext, 1, 1, 1, 1, cv::BORDER_REPLICATE);
	int m1 = image_ext.rows;
	int n1 = image_ext.cols;

	double b = 0.0;
	for (int i = 1; i < m1 - 1; i++)
	{
		for (int j = 1; j < n1 - 1; j++)
		{
			double xy = image_ext.at<uchar>(i, j);
			double x1 = pow((image_ext.at<uchar>(i, j) - image_ext.at<uchar>(i, j + 1)), 2);
			double x2 = pow((image_ext.at<uchar>(i, j) - image_ext.at<uchar>(i, j - 1)), 2);
			double x3 = pow((image_ext.at<uchar>(i, j) - image_ext.at<uchar>(i + 1, j)), 2);
			double x4 = pow((image_ext.at<uchar>(i, j) - image_ext.at<uchar>(i - 1, j)), 2);

			b += ((pow((image_ext.at<uchar>(i, j) - image_ext.at<uchar>(i, j + 1)), 2)) + (pow((image_ext.at<uchar>(i, j) - image_ext.at<uchar>(i, j - 1)), 2))
				+ (pow((image_ext.at<uchar>(i, j) - image_ext.at<uchar>(i + 1, j)), 2)) + (pow((image_ext.at<uchar>(i, j) - image_ext.at<uchar>(i - 1, j)), 2)));
		}
	}
	double cg = b / (4 * (m - 2) * (n - 2) + 3 * (2 * (m - 2) + 2 * (n - 2)) + 2 * 4);
	return cg;
}

__declspec(dllexport) double runfunction(cv::String filename)
{
	Mat image = imread(filename);
	double result = contrast(image);
	return result;
}

对于上述程序,编译后会生成DLL和Lib文件,如下所示。

image.png

对链接库进行调用的实例代码如下

#include <iostream>
#include "detect.h"
using namespace std;

// 这个Dll5.lib是自己生成的DLL文件
#pragma comment(lib,"Dll5.lib")



int main()
{
	SayHello();
	double a = runfunction("D:\\VSWorkSpace\\Project11\\x64\\Debug\\bs.tiff");
	cout << a;
	return 0;
}

结果如下

image.png