matlab imadjust 用 opencv改写

原文:http://blog.youkuaiyun.com/yeyang911/article/details/18256393

自己测试的效果不是很好

实现函数功能

J = low_out +(high_out - low_out).* ((I - low_in)/(high_in - low_in)).^ gamma 


  1. IplImage* ImageAdjust(IplImage *src, IplImage *dst,    
  2.           double low_in, double high_in,    
  3.           double low_out, double high_out, double gamma )    
  4. {    
  5.     double low2 = low_in*255;    
  6.     double high2 = high_in*255;    
  7.     double bottom2 = low_out*255;    
  8.     double top2 = high_out*255;    
  9.     double err_in = high2 - low2;    
  10.     double err_out = top2 - bottom2;    
  11.     
  12.     int x,y;    
  13.     double val0,val1,val2;    
  14.     
  15.     // intensity transform    
  16.     for( y = 0; y < src->height; y++) {    
  17.         for (x = 0; x < src->width; x++){    
  18.             val0 = ((uchar*)(src->imageData+src->widthStep*y))[x*src->nChannels];     
  19.             val0 = pow((val0 - low2)/err_in,gamma)*err_out+bottom2;    
  20.             if(val0>255) val0=255;     
  21.         if(val0<0) val0=0;     
  22.         ((uchar*)(dst->imageData+dst->widthStep*y))[x*src->nChannels]=(uchar)val0;    
  23.     
  24.         val1 = ((uchar*)(src->imageData+src->widthStep*y))[x*src->nChannels+1];     
  25.             val1 = pow((val1- low2)/err_in, gamma)*err_out+bottom2;    
  26.             if(val1>255) val1=255;     
  27.             if(val1<0) val1=0;    
  28.         ((uchar*)(dst->imageData+dst->widthStep*y))[x*src->nChannels+1]=(uchar)val1;    
  29.     
  30.         val2 = ((uchar*)(src->imageData + src->widthStep*y))[x*src->nChannels+2];     
  31.             val2 = pow((val2-low2)/err_in,gamma)*err_out+bottom2;    
  32.             if(val2>255) val2=255;     
  33.         if(val2<0) val2=0; // Make sure src is in the range [low,high]    
  34.         ((uchar*)(dst->imageData+dst->widthStep*y))[x*src->nChannels+2]=(uchar)val2;    
  35.         }    
  36.     }    
  37.     return 0;    
  38. }    


测试代码:

  1. int main()  
  2. {  
  3.     IplImage *src=cvLoadImage("d:/111.JPG",1);  
  4.     CvSize a;  
  5.     a.width=src->width;  
  6.     a.height=src->height;  
  7.     IplImage *dst = cvCreateImage(a,8,3);  
  8.     ImageAdjust(src, dst,    
  9.           0, 0.5,    
  10.           0.5, 1, 1)  ;  
  11.     Mat c = dst;  
  12.     imshow("ss",c);  
  13.     waitKey();  
  14.     return 0;  
  15. }  
  

效果图 原图


EMGU CV 版本

  1. private void imageAdjust(Image<Bgr,byte>src,Image<Bgr,byte>dst,double low_in, double high_in,  
  2.          double low_out, double high_out, double gamma)  
  3.        {  
  4.   
  5.            double low2 = low_in * 255;  
  6.            double high2 = high_in * 255;  
  7.            double bottom2 = low_out * 255;  
  8.            double top2 = high_out * 255;  
  9.            double err_in = high2 - low2;  
  10.            double err_out = top2 - bottom2;  
  11.   
  12.            int x, y;  
  13.            double val0, val1, val2;  
  14.   
  15.            // intensity transform    
  16.            for (y = 0; y < src.Height; y++)  
  17.            {  
  18.                for (x = 0; x < src.Width; x++)  
  19.                {  
  20.                     
  21.   
  22.                    val0 = src.Data[y, x, 0];  
  23.                    val0 =   Math.Pow((val0 - low2) / err_in, gamma) * err_out + bottom2;  
  24.                    if (val0 > 255) val0 = 255;  
  25.                    if (val0 < 0) val0 = 0;  
  26.                    dst.Data[y,x,0] = (byte)val0;  
  27.   
  28.   
  29.                    val1 = src.Data[y, x, 1];  
  30.                    val1 = Math.Pow((val1 - low2) / err_in, gamma) * err_out + bottom2;  
  31.                    if (val1 > 255) val1 = 255;  
  32.                    if (val1 < 0) val1 = 0;  
  33.                    dst.Data[y, x, 1] = (byte)val1;  
  34.   
  35.                    val2 = src.Data[y, x, 2];  
  36.                    val2 = Math.Pow((val2 - low2) / err_in, gamma) * err_out + bottom2;  
  37.                    if (val2 > 255) val2 = 255;  
  38.                    if (val2 < 0) val2 = 0; // Make sure src is in the range [low,high]    
  39.                    dst.Data[y, x, 2] = (byte)val2;  
  40.                }  
  41.            }  
  42.          
  43.   
  44.        }  


上面的代码对于大图运行效率低,下面我写个优化版的

代码如下:

  1. private void imadjust(Image<Gray,byte> src)  
  2.        {  
  3.            double minV , maxV ;  
  4.            int [] minP = new int[2];  
  5.            int [] maxP = new int[2];  
  6.            CvInvoke.MinMaxIdx(src, out minV, out maxV, minP, maxP);  
  7.            Mat m = src.Mat;  
  8.            m.ConvertTo(m, Emgu.CV.CvEnum.DepthType.Cv32F);  
  9.            Mat n = new Mat(m.Size,Emgu.CV.CvEnum.DepthType.Cv32F,1);  
  10.            MCvScalar p = new MCvScalar();  
  11.            p.V0 = 1.0/(maxV-minV);  
  12.            n.SetTo(p);  
  13.            Mat dst = new Mat(m.Size,Emgu.CV.CvEnum.DepthType.Cv32F,1);  
  14.            CvInvoke.Multiply(m, n, dst);  
  15.            p.V0 = 255;  
  16.            n.SetTo(p);//设置矩阵为p.V0 的值  
  17.            CvInvoke.Multiply(dst, n, dst);  
  18.            pictureBox1.Image = dst.ToImage<Gray, byte>().ToBitmap();// 显示到pictureBox上  
  19.        }  

都是采用向量化(矢量化)编程方式,效率不会差,但是我是简单实现,假设输出为最小为0 最大值为255的情况,且gamma 为1时的情况

如果需要别的情形需要自己根据情况编写。

这是另一个版本,只能灰度图:

参考:http://stackoverflow.com/questions/31647274/is-there-any-function-equivalent-to-matlabs-imadjust-in-opencv-with-c

网页还有一个别的,可以测试一下

#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
/*
  src and dst are grayscale, 8-bit images;
  Default input value:
           [low, high] = [0,1];  X-Direction
           [bottom, top] = [0,1]; Y-Direction
           gamma ;
  if adjust successfully, return 0, otherwise, return non-zero.
*/
#include <algorithm>
using namespace std;
using namespace cv;
void imadjust(const Mat1b& src, Mat1b& dst, int tol = 1, Vec2i in = Vec2i(0, 255), Vec2i out = Vec2i(0, 255))
{
    // src : input CV_8UC1 image
    // dst : output CV_8UC1 imge
    // tol : tolerance, from 0 to 100.
    // in  : src image bounds
    // out : dst image buonds
    dst = src.clone();
    tol = max(0, min(100, tol));
    if (tol > 0)
    {
        // Compute in and out limits
        // Histogram
        vector<int> hist(256, 0);
        for (int r = 0; r < src.rows; ++r) {
            for (int c = 0; c < src.cols; ++c) {
                hist[src(r,c)]++;
            }
        }
        // Cumulative histogram
        vector<int> cum = hist;
        for (int i = 1; i < hist.size(); ++i) {
            cum[i] = cum[i - 1] + hist[i];
        }
        // Compute bounds
        int total = src.rows * src.cols;
        int low_bound = total * tol / 100;
        int upp_bound = total * (100-tol) / 100;
        in[0] = distance(cum.begin(), lower_bound(cum.begin(), cum.end(), low_bound));
        in[1] = distance(cum.begin(), lower_bound(cum.begin(), cum.end(), upp_bound));
    }
    // Stretching
    float scale = float(out[1] - out[0]) / float(in[1] - in[0]);
    for (int r = 0; r < dst.rows; ++r)
    {
        for (int c = 0; c < dst.cols; ++c)
        {
            int vs = max(src(r, c) - in[0], 0);
            int vd = min(int(vs * scale + 0.5f) + out[0], out[1]);
            dst(r, c) = saturate_cast<uchar>(vd);
        }
    }
}
int main()
{
    Mat3b img = imread("fish.png");
    Mat1b gray;
    cvtColor(img, gray, COLOR_RGB2GRAY);
    Mat1b adjusted;
    imadjust(gray, adjusted);
    imshow("ss",adjusted);
       waitKey();
    // int low_in, high_in, low_out, high_out
    // imadjust(gray, adjusted, 0, Vec2i(low_in, high_in), Vec2i(low_out, high_out));
    return 0;
}
//int main111( int argc, char** argv )
//{
//    IplImage *src=cvLoadImage("fish.png",1);
//       CvSize a;
//       a.width=src->width;
//       a.height=src->height;
//       IplImage *dst = cvCreateImage(a,8,3);
//       ImageAdjust(src, dst,
//             0, 0.5,
//             0.5, 1, 1)  ;
//       Mat gray_image = cvarrToMat(dst);
//       imshow("ss",gray_image);
//       waitKey();
//    return 0;
//}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值