数字图像处理基本算法实现(1)--section3.2基本灰度变换

来源:互联网 发布:怎样关闭淘宝退款申请 编辑:程序博客网 时间:2024/06/06 14:05

          虽然学的是与图像处理有关的专业,也看过一些图像处理的书,基本的算法原理也懂,但是一直以来都是用现成的库,没有自己按照算法编过,或者有些算法照着别人的代码敲一遍,什么也没学到,所以一直就想好好补补,试着自己去按照算法描述编一下,不管效率,允许小的bug,只是去学习一下,然后与别人的更好的实现对比一下,找找差距。这也快毕业要去工作了,趁着现在有点时间,就试着做一下,不知道能坚持到什么地步,不管怎样,尽力而为了。

        以冈萨雷斯的《数字图像处理(第三版)》为参考文献,使用VS2008,结合OpenCV中的一些函数,当然尽量不用现成的函数,只是用OpenCV的读取,保存,显示图像等。

      第一次,从3.2节开始:

头文件

class section_3_2{public:Mat& imageInverse(Mat &src);Mat& logTrans(Mat &src, bool blog10=false);Mat& expTrans(Mat &src, double basenum=1.1);Mat& gammaTrans(Mat &src, double gamma);Mat& piecewiseLinearTrans(Mat &src, vector<cv::Point> &linearFun);bool bitLayerTrans(Mat &src,vector<Mat>& bitmat, bool binary=false);Mat& bitLayerCombine(vector<Mat> &bitmat, int *bituse, bool binary=false);private:Mat m_destMat;};


实现

#include "processing.h"//image inversionMat& section_3_2::imageInverse(Mat &src){m_destMat.create(src.rows, src.cols, CV_8UC3);int nChanel = src.channels();for (int i=0; i<src.rows; ++i){uchar *src_ptr = src.ptr<uchar>(i);uchar *dest_ptr = m_destMat.ptr<uchar>(i);for (int j=0; j<src.cols; ++j){if(nChanel==1){memset(dest_ptr+3*j, 255-src_ptr[j], 3);}else{int t = 3*j;dest_ptr[t] = 255-src_ptr[t];dest_ptr[t+1] = 255-src_ptr[t+1];dest_ptr[t+2] = 255-src_ptr[t+2];}}}return m_destMat;}//log transformationMat& section_3_2::logTrans(Mat &src, bool blog10){m_destMat.create(src.rows, src.cols, CV_8UC3);float k = blog10 ? 255/log10(256.f) : 255/log(256.f);uchar logtable[256]={0};for(int i=0; i<256; ++i){logtable[i] = (blog10 ? saturate_cast<uchar>(log10(float(i+1))*k) : saturate_cast<uchar>(log(float(i+1))*k));}int nChanel = src.channels();for (int i=0; i<src.rows; ++i){uchar *src_ptr = src.ptr<uchar>(i);uchar *dest_ptr = m_destMat.ptr<uchar>(i);for (int j=0; j<src.cols; ++j){if(nChanel==1){memset(dest_ptr+3*j, logtable[src_ptr[j]], 3);}else{int t = 3*j;dest_ptr[t] = logtable[src_ptr[t]];dest_ptr[t+1] = logtable[src_ptr[t+1]];dest_ptr[t+2] = logtable[src_ptr[t+2]];}}}return m_destMat;}//exponent transformationMat& section_3_2::expTrans(Mat &src, double basenum){if(basenum <= 0)return m_destMat;m_destMat.create(src.rows, src.cols, CV_8UC3);double k = 255/(pow(basenum, 255)-1);uchar exptable[256]={0};for(int i=0; i<256; ++i){exptable[i] = saturate_cast<uchar>((pow(basenum, i)-1)*k);}int nChanel = src.channels();for (int i=0; i<src.rows; ++i){uchar *src_ptr = src.ptr<uchar>(i);uchar *dest_ptr = m_destMat.ptr<uchar>(i);for (int j=0; j<src.cols; ++j){if(nChanel==1){memset(dest_ptr+3*j, exptable[src_ptr[j]], 3);}else{int t = 3*j;dest_ptr[t] = exptable[src_ptr[t]];dest_ptr[t+1] = exptable[src_ptr[t+1]];dest_ptr[t+2] = exptable[src_ptr[t+2]];}}}return m_destMat;}//gamma transformationMat& section_3_2::gammaTrans(Mat &src,double gamma){if(gamma<=0)return m_destMat;m_destMat.create(src.rows, src.cols, CV_8UC3);double k = 255/(pow(255.0, gamma)-1);uchar gammatable[256]={0};for(int i=0; i<256; ++i){gammatable[i] = saturate_cast<uchar>((pow(double(i), gamma)-1)*k);}int nChanel = src.channels();for (int i=0; i<src.rows; ++i){uchar *src_ptr = src.ptr<uchar>(i);uchar *dest_ptr = m_destMat.ptr<uchar>(i);for (int j=0; j<src.cols; ++j){if(nChanel==1){memset(dest_ptr+3*j, gammatable[src_ptr[j]], 3);}else{int t = 3*j;dest_ptr[t] = gammatable[src_ptr[t]];dest_ptr[t+1] = gammatable[src_ptr[t+1]];dest_ptr[t+2] = gammatable[src_ptr[t+2]];}}}return m_destMat;}//piecewise linear transformationMat& section_3_2::piecewiseLinearTrans(Mat &src, vector<cv::Point> &linearFun){//at least two end points,first-0, last-255;if(linearFun.size()<2 || linearFun[0].x!=0 || linearFun[linearFun.size()-1].x!=255)return m_destMat;//check each point--every point's x coord should not less than the last one;for (size_t i=1; i<linearFun.size(); ++i){if(linearFun[i].x<linearFun[i-1].x || linearFun[i-1].x>255 || linearFun[i].x>255 || linearFun[i-1].y>255 || linearFun[i].y>255)return m_destMat;}m_destMat.create(src.rows, src.cols, CV_8UC3);//create the lookup table;uchar sectable[256]={0};int uplimit = min(256, linearFun[1].x);size_t j=0;for(int i=0;;){float k = (linearFun[j+1].y-linearFun[j].y)/(float)(linearFun[j+1].x-linearFun[j].x);for(; i<=uplimit; ++i){uchar pix = 0;//not verticalif(linearFun[j].x < linearFun[j+1].x){pix = saturate_cast<uchar>(linearFun[j].y+k*(i-linearFun[j].x));}else{//verticalpix = linearFun[j].y;}sectable[i] = pix;}//shift the section and checkif (++j < linearFun.size()-1){uplimit = linearFun[j+1].x;}else{for (;i<256; ++i){sectable[i] = 255;}break;}}//scan input image and set the outputint nChanel = src.channels();for (int i=0; i<src.rows; ++i){uchar *src_ptr = src.ptr<uchar>(i);uchar *dest_ptr = m_destMat.ptr<uchar>(i);for (int j=0; j<src.cols; ++j){if(nChanel==1){memset(dest_ptr+3*j, sectable[src_ptr[j]], 3);}else{int t = 3*j;dest_ptr[t] = sectable[src_ptr[t]];dest_ptr[t+1] = sectable[src_ptr[t+1]];dest_ptr[t+2] = sectable[src_ptr[t+2]];}}}return m_destMat;}//bit layer transformationbool section_3_2::bitLayerTrans(Mat &src,vector<Mat>& bitmat, bool binary){if(src.channels() != 1)return false;m_destMat = Mat::zeros(src.rows, src.cols, CV_8UC3);bitmat.clear();//create a 8 elements vector, //note!- cv::Mat is ref-count,so don't just push_back it; copy to new Mat;for(int i=0; i<8; ++i){Mat temp;m_destMat.copyTo(temp);bitmat.push_back(temp);}for (int i=0; i<src.rows; ++i){uchar *src_ptr = src.ptr<uchar>(i);for (int j=0; j<src.cols; ++j){uchar maskbyte = 0x01;for (int k=0; k<8; ++k){uchar *dest_ptr = bitmat[k].ptr<uchar>(i);uchar pixvalue = 0;if(binary)pixvalue = (src_ptr[j]&(maskbyte<<k))==0 ? 0 : 255;elsepixvalue = src_ptr[j]&(maskbyte<<k);memset(dest_ptr+3*j, pixvalue, 3);}}}return true;}//combine specified bit image to a new one;//param: bituse should be 8 elements arrays, if elem k is not 0,then use this bit;//param: binary indicate whether the vector<Mat> is binary image;Mat& section_3_2::bitLayerCombine(vector<Mat> &bitmat, int *bituse, bool binary){if(bitmat.size()!= 8)return m_destMat;m_destMat = Mat::zeros(bitmat[0].rows, bitmat[0].cols, CV_8UC3);for (int i=0; i<m_destMat.rows; ++i){uchar *dest_ptr = m_destMat.ptr<uchar>(i);for (int j=0; j<m_destMat.cols; ++j){uchar maskbyte = 0x01;uchar pixvalue = 0;int j3 = j*3;for (int k=0; k<8; ++k){if(!bituse[k])continue;uchar *src_ptr = bitmat[k].ptr<uchar>(i);if(binary)pixvalue |= (src_ptr[j3]&(maskbyte<<k));elsepixvalue |= src_ptr[j3];}memset(dest_ptr+j3, pixvalue, 3);}}return m_destMat;}


下面给出几张处理的图像:

分别是反转,gamma=0.5和log变换

分别是分段线性变换和指数变换后和指数变换前的图像

下面是比特分层的lena图像,左->右,上->下,分别为bit0--bit7的图像

下面是使用分层图像组合起来的图像

从左到右分别为使用bit6和bit7;bit5,bit6和bit7;bit3--bit7组合之后的图像,第三幅已经非常接近原始图像。

 

原创粉丝点击