基于opencv的相机之调整功能实现(七)

简介

  本篇是对实现图片处理功能:【调整】实现的记录。

亮度调整

实现原理

  利用公式:g(i,j) = contrast*f(i,j)+brightness。在原图像基础上,根据拖动条的数据大小,整体的加上或者减去不同的brightness。
实现图像的亮度调整。

具体代码

JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicBrightness
    (JNIEnv* env, jclass obj, jlong imageBrightness, jint value){
    double beta = 0.0, alpha = 1.0;
 
    value = value - 50;
    beta = value * 2;
 
    Mat mat = Mat(*((Mat*)imageBrightness));
    mat.convertTo(mat, -1, alpha, beta);
}

函数传入的参数value就是对应拖动条的数据,范围在0到100之间,beta为需要被加上的亮度数据。

当大于50的时候,beta范围为0 - 100,对应图片mat亮度增加。
当小于50的时候,deta范围为0 - (-100),对应图片亮度降低。

效果演示

  对应的效果图片如下:
         
                      亮度降低                     亮度增加


AWB调整

实现原理

  简单的说就是,图像R和B通道数据的增减,来实现图像整体偏冷或者偏暖。

具体代码

JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicAWB                                             
    (JNIEnv* env, jclass obj, jlong imageAWB, jint value){
    int width, height, k, j;
    IplImage src1;
    CvScalar s1;
 
    Mat mat = Mat(*((Mat*)imageAWB));
    src1 = mat;
    width = mat.rows;
    height = mat.cols;
 
    if(value > 50){
        value = (value - 50) * 2;
        for(k = 0; k < width; k++){
            for(j= 0; j< height; j++){
                s1 = cvGet2D(&src1, k, j);
                s1.val[0] = s1.val[0] + value;
                cvSet2D(&src1, k, j, s1);
            }
        }
    }else{
        value = (50 - value) * 2;
        for(k = 0; k < width; k++){
            for(j= 0; j< height; j++){
                s1 = cvGet2D(&src1, k, j);
                s1.val[2] = s1.val[2] + value;
                cvSet2D(&src1, k, j, s1);
            }
        }
    }
}

同样的函数传入的参数value就是拖动条数据,拖动条默认数据为50。当大于50的时候,增加图像R通道的数据,让图像偏暖;当小于50的时候,

增加图像B通道的数据,让图像偏冷。

效果演示

  对应的效果图片如下:
    
           偏冷效果                  偏暖效果

对比度调整

实现原理

  同样利用公式:g(i,j) = contrast*f(i,j)+brightness。在原图像基础上,根据拖动条的数据大小,整体的乘上contrast,根据contrast的不同,来实现图像的亮度调整。

具体代码

JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicContrast                                                       
  (JNIEnv* env, jclass obj, jlong imageContrast, jint value){
    double alpha = 1.0;
 
    if(value > 50){
        value = value - 50;
        alpha = alpha + ((double)value / 25);
    }else{
        alpha = alpha - ((double)(50 - value) / 50);    
    }
 
    Mat mat = Mat(*((Mat*)imageContrast));
    mat.convertTo(mat, -1, alpha, 0);
}

同样的,拖动条数据value默认为50,当value大于50的时候,alpha也就是contrast大于1,对比机增加;当value小于50的时候,alpha小于1,对比多降低。

效果演示

  对应的效果图片如下:
        
              对比度增加                     对比度降低

饱和度调整

实现原理

  将rgb图像,转换为hsv格式之后,其中的s分量就表示为饱和度,通过增加、减小该分量来实现饱和度的增减。

具体代码

JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicSaturation                                                     
  (JNIEnv* env, jclass obj, jlong imagePicsaturation, jint value){
    int width, height, k, j;
    CvScalar s1;
    IplImage src;
 
    Mat mat = Mat(*((Mat*)imagePicsaturation));
    src = mat;
    IplImage *hsv_img = cvCreateImage(cvGetSize(&src), 8 , 3);
 
    width = mat.rows;
    height = mat.cols;
 
    cvCvtColor(&src, hsv_img, CV_BGR2HSV);
 
    value = (value - 50) * 2;
    for(k = 0; k < width; k++){
        for(j= 0; j< height; j++){
            s1 = cvGet2D(hsv_img, k, j);
            s1.val[1] = s1.val[1] + value;
            if(s1.val[1] < 0){
                s1.val[1] = 0;  
            }else if(s1.val[1] > 255){
                s1.val[1] = 255;
            }
            cvSet2D(hsv_img, k, j, s1);
        }
    }
    cvCvtColor(hsv_img, &src, CV_HSV2BGR);
}

   首先将图像转换为HSV格式,接着根据拖动条数值是大于50还是小于50,来计算是增加S通道分量还是降低S通道分量。最后将图像从新转换会BGR格式。

效果演示

  对应的效果图片如下:
    
                饱和度增加                   饱和度降低

锐度调整

实现原理

  通过对图像的模糊来降低图像锐度;首先将图像模糊,接着用模糊图像减去原图像,再与原图像相加,从而增加图像锐度。

具体代码

JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicSharpness                                                      
(JNIEnv* env, jclass obj, jlong imageSharpness, jint value){
    int width, height, i, j;
    IplImage pI_1, pI_2;
    CvScalar s1, s2;
    Mat mat1 = Mat(*((Mat*)imageSharpness));
    width = mat1.rows;
    height = mat1.cols;
    Mat mat2 = cv::Mat(width, height, CV_8UC3, 1);
    int sharpness_now;
 
    pI_1 = mat1;
    pI_2 = mat2;
     
    if(value < 50){
        sharpness_now =  3 +  2 *((50 - value) / 10);
        cvSmooth(&pI_1, &pI_2, CV_GAUSSIAN, sharpness_now, 0, 0, 0);
        for(i=0; i<width; i++){
            for(j=0; j<height; j++){
                s1 = cvGet2D(&pI_1, i, j);
                s2 = cvGet2D(&pI_2, i, j);
                s1.val[0] = s2.val[0];
                s1.val[1] = s2.val[1];
                s1.val[2] = s2.val[2];
                cvSet2D(&pI_1, i, j, s1);
            }
        }
    }else{
        sharpness_now =  3 + 2 * ((value - 50) / 10);
        cvSmooth(&pI_1, &pI_2, CV_GAUSSIAN, sharpness_now, 0, 0, 0);
        for(i=0; i<width; i++){
            for(j=0; j<height; j++){
                s1 = cvGet2D(&pI_1, i, j);
                s2 = cvGet2D(&pI_2, i, j);
                s1.val[0] = s1.val[0] - s2.val[0];
                s1.val[1] = s1.val[1] - s2.val[1];
                s1.val[2] = s1.val[2] - s2.val[2];
                cvSet2D(&pI_2, i, j, s1);
            }
        }
        for(i=0; i<width; i++){
            for(j=0; j<height; j++){
                s1 = cvGet2D(&pI_1, i, j);
                s2 = cvGet2D(&pI_2, i, j);
                s1.val[0] = s1.val[0] + s2.val[0];
                s1.val[1] = s1.val[1] + s2.val[1];
                s1.val[2] = s1.val[2] + s2.val[2];
                cvSet2D(&pI_1, i, j, s1);
            }
        }
    }
}

   当拖动条数据value小于50的时候,使用cvSmooth直接对图像进行模糊;当value大于50的时候,首先cvSmooth模糊图像到pI_2中,接着pI_2减去原图像、pI_1,处理后的数据,继续放入pI_2中。最后将pI_2的数据和原图像pI_1相加,达到锐化效果。

效果演示

  对应的效果图片如下:
      
                   锐度降低                     锐度增加

亮处细节

实现原理

  首先统计出图像[0,255]的直方图数据,计算出图像像素从0开始到占据所有像素点50%时候的像素值;接着计算出到占据80%时候的对应的像素值。剩下20%的像素点,默认为亮处数据,之前统计的80%数据为非亮处像素。
  将80%的非亮处像素,从新映射到0到之前50%时候像素值范围,将20%的亮处数据映射到之前统计的50%像素值到本图像最大像素值区间范围内。
    相当于增大了亮处数据的对比度。从而使得亮处的细节更加清楚。

具体代码

JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicBrightnessDetile
    (JNIEnv* env, jclass obj, jlong imageDarkdetile, jint value){
    int width, height, i, j;
    IplImage src1;
    CvScalar s1;
    int hist_size = 256;
    int hist_height = 256; 
    IplImage* Y_plane;
    CvHistogram* Y_hist;
    float range[] = {0,255};
    float* ranges[]={range};
    float high_val[2], tmp;
    float scale[hist_size];
    float scale_number[hist_size];
    float scale_flag[2];
    float throwld = 0.4 + value / 333.3;
 
    Mat mat = Mat(*((Mat*)imageDarkdetile));
    src1 = mat;
    width = mat.rows;
    height = mat.cols;
    cvCvtColor(&src1, &src1, CV_BGR2YCrCb);
    Y_plane  = cvCreateImage(cvGetSize(&src1), 8, 1);
    cvSplit(&src1, Y_plane, NULL, NULL, NULL);
    Y_hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
 
    cvCalcHist(&Y_plane, Y_hist, 0, 0);
    cvNormalizeHist(Y_hist, 1.0);
 
    for(i=0; i<hist_size; i++){
        high_val[0] = cvQueryHistValue_1D(Y_hist, i);
        scale[i] = 0;
        if(i == 0){
            scale[i] = high_val[0];
        }else{
            scale[i] = scale[i - 1] + high_val[0];
        }
        if(scale[i] < throwld){
            scale_flag[0] = i;
        }else if(scale[i] > 0.8){
            scale_flag[1] = i;
            high_val[0] = scale_flag[0] / scale_flag[1];
            high_val[1] = (255.0 - scale_flag[0]) / (255.0 - scale_flag[1]);
            break;
        }
    }
 
    for(i=0; i<width; i++){
        for(j=0; j<height; j++){
            s1 = cvGet2D(&src1, i, j);
            if(s1.val[0] < scale_flag[1]){
                s1.val[0] = s1.val[0] * high_val[0];
            }else{
                s1.val[0] = scale_flag[0] + (s1.val[0] - scale_flag[1]) * high_val[1];
                if(s1.val[0] > 255){
                    s1.val[0] = 255;
                }
            }
            cvSet2D(&src1, i, j, s1);
        }
    }
    cvCvtColor(&src1, &src1, CV_YCrCb2BGR);

   将图像转化为YCrCb格式,接着分离出Y通道,对y通道数据统计直方图,throwld 对应为之前说的50%阀值,该阀值根据拖动条变化,阀值越低,亮处

细节效果越明显,将阀值throwld和80%处的像素值大小,保存到scale_flag数组中。接着计算出从新映射的公式。
  最后通过:
            s1.val[0] = s1.val[0] * high_val[0];
            s1.val[0] = scale_flag[0] + (s1.val[0] - scale_flag[1]) * high_val[1];
    对图像亮处像素和非亮处像素进行重新映射,然后将图像格式从新转换回BGR格式。

效果演示

  对应的效果图片如下:
          
         原图像                                     亮处细节                                 

暗处细节

实现原理

  和之前的亮度细节类似,区别是亮处细节时候,是从0开始统计到50%为阀值,80%以上为亮处细节。这里是从255开始。像素值递减的统计,也是50%为阀值。
    80%以上的数据的暗处细节。最后将非暗处细节的数据,从新映射到255开始统计的,50%像素范围内,将暗处细节数据映射到50%像素开始到像素 值为0的像素范围内。

具体代码

JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicDarkDetile
    (JNIEnv* env, jclass obj, jlong imageDarkdetile, jint value){
    int width, height, i, j = 0;
    IplImage src1;
    CvScalar s1;
    int hist_size = 256;
    int hist_height = 256; 
    IplImage* Y_plane;
    CvHistogram* Y_hist;
    float range[] = {0,255};
    float* ranges[]={range};
    float high_val[2], tmp;
    float scale[hist_size];
    float scale_number[hist_size];
    float scale_flag[2];
    float throwld = 0.4 + value / 333.3;
 
    Mat mat = Mat(*((Mat*)imageDarkdetile));
    src1 = mat;
    width = mat.rows;
    height = mat.cols;
    cvCvtColor(&src1, &src1, CV_BGR2YCrCb);
    Y_plane  = cvCreateImage(cvGetSize(&src1), 8, 1);
    cvSplit(&src1, Y_plane, NULL, NULL, NULL);
    Y_hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
 
    cvCalcHist(&Y_plane, Y_hist, 0, 0);
    cvNormalizeHist(Y_hist, 1.0);
 
    for(i=hist_size - 1; i>0; i--){
        high_val[0] = cvQueryHistValue_1D(Y_hist, i);
        scale[j] = 0;
        if(j == 0){
            scale[j] = high_val[0];
        }else{
            scale[j] = scale[j - 1] + high_val[0];
        }
        if(scale[j] < throwld){
            scale_flag[0] = i;
        }else if(scale[j] > 0.8){
            scale_flag[1] = i;
            high_val[0] = (255.0 - scale_flag[0]) / (255.0 - scale_flag[1]);
            high_val[1] = scale_flag[0] / scale_flag[1];
            break;
        }
        j++;
    }
 
    for(i=0; i<width; i++){
        for(j=0; j<height; j++){
            s1 = cvGet2D(&src1, i, j);
            if(s1.val[0] > scale_flag[1]){
                s1.val[0] = scale_flag[0] + (s1.val[0] - scale_flag[1]) * high_val[0];
            }else{
                s1.val[0] = s1.val[0] * high_val[1];
            }
            cvSet2D(&src1, i, j, s1);
        }
    }
    cvCvtColor(&src1, &src1, CV_YCrCb2BGR);     
}

效果演示

  对应的效果图片如下:
          
         原图像                                    暗处细节
具体演示下载:http://download.csdn.net/detail/u011630458/9261617
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值