首页 > 编程知识 正文

基于像素的像增强方法,基于opencv的像分割算法

时间:2023-05-04 03:36:21 阅读:228857 作者:3826

1 基于图像单像素点的处理

看过数字图像处理一书的都知道,图像处理中基于像素点的处理分为两种
灰度变换:本质就是基于单像素点的变化处理。
空间滤波:本质就是基于邻域像素点的变化处理。
今天要讲的是在OpenCv下基于基于单像素点的处理,其中会讲到OpenCv针对单像素处理封装好的一些ApI,即实质原理。

1.1 图像像素点的访问

要进行基于单像素点的处理,首先就必须知道,给你一幅图,你如何去访问图中的每一个像素点。无论是网上还是各种教程书上都给出了三种访问像素点的方式,分别是:
1、 指针访问。实质就是通过数据指针直接访问数据。
2、 迭代器访问。类似STL中容器的访问。
3、 动态地址计算。将每个像素转换为对应类型(uchar或Vec3b),再进行访问。
下面以为图像中每个像素点加1为例说明三种方法。

/************************************************//*访问图像像素点的三种方法/************************************************/int rows = img.rows;int cols = img.cols;int channels = img.channels();uchar *pRow = 0;// 方法一:指针法访问for (int i = 0; i < rows; ++i){// 获取行指针pRow = img.ptr<uchar>(i);for (int j = 0; j < cols; ++j){if (channels == 1) //单通道{pRow[j] = pRow[j] + 1;}else if (channels == 3) //三通道{pRow[j * 3 ] = pRow[j * 3 ] + 1;pRow[j * 3 + 1] = pRow[j * 3 + 1] + 1;pRow[j * 3 + 2] = pRow[j * 3 + 2] + 1;}}}// 方法一:迭代器法访问、事先得知道图像通道数,这里假设为3通道Mat_<Vec3b>::iterator it = img.begin<Vec3b>(); //初始位置迭代器Mat_<Vec3b>::iterator end = img.end<Vec3b>(); //终止位置迭代器for (; it != end; ++it){(*it)[0] = (*it)[0] + 1;(*it)[1] = (*it)[1] + 1;(*it)[2] = (*it)[2] + 1;}// 方法一:动态地址访问、事先得知道图像通道数,这里假设为3通道for (int i = 0; i < rows; ++i){for (int j = 0; j < cols; ++j){if (channels == 1) //单通道{img.at<uchar>(i,j) = img.at<uchar>(i, j)+1;}else if (channels == 3) //三通道{img.at<Vec3b>(i, j)[0] = img.at<Vec3b>(i, j)[0] + 1;img.at<Vec3b>(i, j)[1] = img.at<Vec3b>(i, j)[1] + 1;img.at<Vec3b>(i, j)[2] = img.at<Vec3b>(i, j)[2] + 1;}}} 1.2 图像亮度和对比度调整

知道如何对图像单像素点进行操作后,其实就可以对图像进行很多操作了,其中最有用,最让人产生直观感受的就是亮度和对比度的调整了。
基于单像素点变换分为以下几种:r为源像素点值,s为变换后像素点值。这里的值有可能是灰度图像中的灰度值,RGB颜色模型中的红、绿、蓝分量值,或者是HSV颜色模型中的色调、饱和度、亮度值。
1、 翻转变换

s=L-1-r 2、 线性变换 s=a*r+b 作用:a控制对比度,b控制亮度。 3、 对数变化 s=clog(1+r) 作用:围较窄的低灰度值映射到范围较宽的灰度区间,同时将范围较宽的高灰度值区间映射为较窄的灰度区间,从而扩展了暗像素的值,压缩了高灰度的值,能够对图像中低灰度细节进行增强。 4、幂(伽马)变换 s=cr^γ 作用: 当γ=c=1时:恒等变换。 当c=1,γ<1时:扩展低灰度级范围,压缩高灰度级范围,灰度值整体增大,变亮。γ 的值越小,对图像低灰度值的扩展越明显。 当c=1,γ>1时:压缩低灰度级范围,扩展高灰度级范围,灰度值整体减小,变暗。γ的值越大,对图像高灰度值部分的扩展越明显。 伽马变换主要用于图像的校正,对灰度值过高(图像过亮)或者过低(图像过暗)的图像进行修正,增加图像的对比。 值得注意的是上述4个变换中,除了翻转变换结果不可能溢出,即值在范围0-255之间,其他的都有可能溢出,特别是线性变换还可能出现负值。下面就以线性变换为例写一个小例子。例子是基于QT的,但不妨碍理解。 主要源码:void QtGuiApplication1::update(){int rows = m_Sor.rows;int cols = m_Sor.cols;int channels = m_Sor.channels();uchar *pSorRow = 0;uchar *pDstRow = 0;float contrast = m_Value1 / 10.f;// 方法一:指针法访问for (int i = 0; i < rows; ++i){// 获取行指针pSorRow = m_Sor.ptr<uchar>(i);pDstRow = m_Dst.ptr<uchar>(i);for (int j = 0; j < cols; ++j){if (channels == 1) //单通道{pDstRow[j] = pSorRow[j] + 1;}else if (channels == 3) //三通道{pDstRow[j * 3] = saturate_cast<uchar>(pSorRow[j * 3]* contrast + m_Value2);pDstRow[j * 3 + 1] = saturate_cast<uchar>(pSorRow[j * 3 + 1] * contrast + m_Value2);pDstRow[j * 3 + 2] = saturate_cast<uchar>(pSorRow[j * 3 + 2] * contrast + m_Value2);}}}//normalize(m_Dst, m_Dst, 0, 255,NORM_MINMAX);imshow("Dst", m_Dst);} 使用到的opencv API: saturate_cast(v)

作用:将输入值V限制在给定类型T范围内。

normalize()

void normalize( InputArray src, InputOutputArray dst, double alpha = 1, double beta = 0,
int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray());
参数:src:输出数组。
dst:输出数组。
alpha:参数。
beta:参数。
norm_type:类型。
dtype:输出数组的元素类型。默认和src一致。
mask:是否对src中的指定元素变换,默认全部元素变换。
norm_type取值:

作用:归一化函数,将数值限制在指定范围内,值得注意的是该函数支持输入值为负数哟。对数变换和指数变换后都需要使用该函数进行范围限制。

1.3 颜色空间缩减

什么是颜色空间缩减,目前我们接触到的图像都是256个灰度值的图像,对于显示来说自然是灰度值等级越多,图像越细腻,但是进行图像处理的时候可不是灰度值等级越多越好,而是适当就行,什么是适合呢?是100个灰度等级还是10个灰度等级,这得要具体情况具体对待了。
颜色空间缩减非常简单,一个公式就能明白,例如我们要把256个灰度级缩减到26个灰度级,那么
s=r/10*10
即对每个像素点都进行上述变换,那么一幅256个灰度级的图像最终就变为26个灰度级的图像。
为了提高提高变换的效率,这里可使用查表法,就是预先把每个灰度值将要变换为的灰度值体现算好,放在表中,变换时直接查表。Opencv提供了一个现成的API专门处理的这种查表式变换。

源码例子:#include "QtGuiApplication1.h"//#define Ui#ifndef Ui#include <QFileInfo>#include <QDir>#include <opencv2opencv.hpp>using namespace cv;#else#include <QtWidgets/QApplication>#endifint main(int argc, char *argv[]){QApplication a(argc, argv);#ifdef UiQtGuiApplication1 w;w.show();return a.exec();#elseQString path = QFileInfo(QCoreApplication::applicationDirPath(), "../../../../../").absoluteDir().absolutePath() + "/imgs/";Mat src = imread(path.toStdString() + "sor1.jpg", IMREAD_GRAYSCALE);imshow("src", src);int divideWith = 50;Mat table(1,256,CV_8U);for (int i = 0; i < 256; ++i){table.data[i] = (i / divideWith) * divideWith;}Mat dst;LUT(src, table, dst);imshow("dst", dst);waitKey();return 0;#endif}

效果图:明显灰度级较少之后,图片变得很粗糙了。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。