先介绍一下掩膜操作吧
掩膜操作就是对比度的调整,掩膜操作就是重新计算每个像素的像素值,掩膜(mask也被称为 kernel);
每个像素实现这个公式 I(i,j) = 5*I(i,j) - [I(i,j-1) + I(i,j+1) + I(i-1,j) + I(i+1,j)],所以边上的像素点不能进行掩膜操作;
感觉出来的结果好像就是只有对比度的调整,没有清晰度的调整。

等我学了清晰度的调整,我会把这张图片,调整清晰,放到下面。
先介绍一下一些opencv的语法
(1)获取矩阵的行指针ptr函数 const uchar *current = scr.ptr<uchar>(row); scr为Mat(矩阵),row是那一行
(2)获取矩阵每个像素的通道数 int offsetx = scr.channels();
(3)像素的点值处理函数,在0~255之间的数,原值返回,小于0的数,返回0,大于255的数,返回255
saturate_cast<uchar>(uchar数值);
(4)filter2D现在感觉这个函数挺强大,网上说它的作用,是做卷积操作的,现在的我,还不能更好的理解它,先说一下参数的意思吧
OpenCV中常用filter2D来自定义卷积核,以实现卷积操作;其定义如下:
CV_EXPORTS_W void filter2D( InputArray src, // 输入图像
OutputArray dst, // 输出图像,尺寸、通道数均与原图相等
int ddepth, // m目标图像的深度,如果没有定义则保持与原图一致;原图像和目标图像支持一下深度
src.depth() = CV_8U, ddepth = -1/CV_16S/CV_32F/CV_64F
src.depth() = CV_16U/CV_16S, ddepth = -1/CV_32F/CV_64F
src.depth() = CV_32F, ddepth = -1/CV_32F/CV_64F // r如果设置的值为 -1 ,则表示与输入图像深度一样
src.depth() = CV_64F, ddepth = -1/CV_64F // 可以发现目标图像仅支持与输入图像相同或者比输入图像更深的的模式
InputArray kernel, // 卷积核或者相关核,一个单通道浮点型矩阵,因此如果处理的是多通道图像,则需要
// 先将输入图像 split 成单通道图像,处理完之后再 merge 一下,即可
Point anchor=Point(-1,-1), // 卷积核的基准点(anchor),默认值为(-1,-1),即核的中心位置
// 基准点即核中与要处理的像素重合的地方
double delta=0, // 存储目标图像时可以添加到像素中的值,默认值为 0
int borderType=BORDER_DEFAULT ); // 对图像边缘的处理,因为卷积时图像的边缘无法处理,必须适当的放大
// 边缘,才能够进行处理,默认值表示对全部边缘都进行处理
下面看一下,做掩膜操作吧,代码:
// CVtest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
using namespace cv;
int main()
{
Mat scr = imread("C:\\Users\\Geek\\Desktop\\1281425_2019-07-18_10_0\\hua.jpg");
if (scr.data)
{
printf("图片加载成功!");
}
namedWindow("hua", WINDOW_AUTOSIZE);
imshow("hua", scr);
// 进行掩膜操作。
// 掩膜操作就是对比度的调整,掩膜操作就是重新计算每个像素的像素值,掩膜(mask也被称为 kernel);
// 每个像素实现这个公式 I(i,j) = 5*I(i,j) - [I(i,j-1) + I(i,j+1) + I(i-1,j) + I(i+1,j)],所以边上的像素点不能进行掩膜操作;
Mat out_img;
out_img = Mat::zeros(scr.size(), scr.type()); // 创建一个和scr一样大小的,类型一样的全黑图像。
int rows = scr.rows;
int offsetx = scr.channels(); //每个像素的通道个数;
int cols = (scr.cols - 1)*offsetx; // 边缘的像素点的不做处理
for (int row = 1; row < rows-1; row++)
{
const uchar *previous = scr.ptr<uchar>(row - 1); // 获取当前行的指针;
const uchar *current = scr.ptr<uchar>(row);
const uchar *next = scr.ptr<uchar>(row + 1);
uchar *out = out_img.ptr<uchar>(row); // 这个不是常数,是个可变的值,不能定义为const。
for (int col = offsetx; col < cols; col++)
{
out[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col])); // 这里左右加的是offsetx,每个像素的通道个数。
}
}
/* 把上面的掩膜操作,注释掉,就这两行就可以代替。
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(scr, out_img, scr.depth(), kernel);
*/
namedWindow("掩膜后图", WINDOW_AUTOSIZE);
imshow("掩膜后图", out_img);
waitKey(0);
return 0;
}

690





