OpenCV之图像处理(七) 调整图像亮度与对比度

图像变换可以看作如下:
     - 像素变换 – 点操作
     - 邻域操作 – 区域
    调整图像亮度和对比度属于像素变换-点操作   (图像越亮,颜色值越往255靠近)
        公式: g(i,j) = α*f(i,j)+β  其中 α>0, β是增益变量   这里说的是RGB(0-255)格式的图像,所以α要大于0,对于tif格式图像,颜色数据是可以小于零的
    对比度: 就是两个像素点之间的差值,差值越大对比度越高,反之越低

vs代码

    #include "../common/common.hpp"

    void main1_7(int argc, char ** argv)
    {
        Mat src = imread(getCVImagesPath("images/test1_3.png"), IMREAD_COLOR);
        imshow("src", src);
        int height = src.rows;
        int width = src.cols;
        Mat dst = Mat::zeros(src.size(), src.type());
        float alpha = 1.2f;
        float beta = 10.f;
        Mat convert, dst_convert;
        src.convertTo(convert, CV_32F);
        imshow("convert", convert);//float型的图像显示不出来。。 在java中也无法将float型的Mat转换成bitmap
        dst_convert = Mat::zeros(src.size(), src.type());
        Mat gray;
        cvtColor(src, gray, COLOR_BGR2GRAY);
        imshow("gray", gray);
        Mat dst_gray = Mat::zeros(gray.size(), gray.type());
        for (int row = 0; row < height; row++)
        {
            for (int col = 0; col < width; col++)
            {
                uchar b = src.at<Vec3b>(row, col)[0];
                uchar g = src.at<Vec3b>(row, col)[1];
                uchar r = src.at<Vec3b>(row, col)[2];
                dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(alpha*b + beta);//调整对比度与亮度,公式: g(i,j) = α*f(i,j)+β  其中 α>0, β是增益变量
                dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(alpha*g + beta);//图像越亮,颜色值越往255靠近
                dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(alpha*r + beta);//对比度: 就是两个像素点之间的差值,差值越大对比度越高,反之越低

                float f_b = convert.at<Vec3f>(row, col)[0];
                float f_g = convert.at<Vec3f>(row, col)[1];
                float f_r = convert.at<Vec3f>(row, col)[2];
                dst_convert.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(alpha*f_b + beta);//用float计算会比uchar精度高一些,值会大一点点
                dst_convert.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(alpha*f_g + beta);
                dst_convert.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(alpha*f_r + beta);

                uchar v = gray.at<uchar>(row, col);
                dst_gray.at<uchar>(row, col) = saturate_cast<uchar>(alpha*v + beta);//灰度图也是一样的计算
            }
        }
        imshow("dst", dst);
        imshow("dst_convert", dst_convert);
        imshow("dst_gray", dst_gray);

        waitKey(0);
    }

效果图

这里写图片描述

android代码

@BindView(R.id.iv_cv1_7_input) ImageView mSrcIv;
@BindView(R.id.iv_cv1_7_output1) ImageView mSrcUcharIv;
@BindView(R.id.iv_cv1_7_output2) ImageView mSrcFloatIv;
@BindView(R.id.iv_cv1_7_output3) ImageView mGrayIv;
@BindView(R.id.iv_cv1_7_output4) ImageView mGrayUcharIv;
private Bitmap mSrcBmp;
private Bitmap mSrcUcharBmp;
private Bitmap mSrcFloatBmp;
private Bitmap mGrayBmp;
private Bitmap mGrayUcharBmp;
private Mat mSrcMat = new Mat();
private Mat mSrcUcharMat;
private Mat mSrcFloatMat;
private Mat mGrayMat = new Mat();
private Mat mGrayUcharMat;
private float alpha = 1.2f;
private float beta = 10.f;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_cv1_7);
    mUnbinder = ButterKnife.bind(this);

    //src
    mSrcBmp = CV310Utils.getBitmapFromAssets(this, "opencv/test1_3.png");
    mSrcIv.setImageBitmap(mSrcBmp);
    Utils.bitmapToMat(mSrcBmp, mSrcMat);
    initBitmaps(mSrcBmp);

    //src uchar
    int height = mSrcMat.rows();
    int width = mSrcMat.cols();
    mSrcUcharMat = Mat.zeros(mSrcMat.size(), mSrcMat.type());
    //convert src float
    Mat mat = new Mat();//转换成float的Mat
    mSrcMat.convertTo(mat, CvType.CV_32F);
    mSrcFloatMat = Mat.zeros(mat.size(), mat.type());
    //gray
    Imgproc.cvtColor(mSrcMat, mGrayMat, Imgproc.COLOR_BGR2GRAY);
    CV310Utils.mat2bitmapAndShowInIv(mGrayMat, mGrayBmp, mGrayIv);
    mGrayUcharMat = Mat.zeros(mGrayMat.size(), mGrayMat.type());
    long start = System.currentTimeMillis();
    for (int row = 0; row < height; row++) {
        for (int col = 0; col < width; col++) {
            //src uchar
            byte rgbaUchar[] = new byte[4];
            mSrcMat.get(row, col, rgbaUchar);
            byte r = changeContractAndBrightness(rgbaUchar[0]);//调整对比度与亮度,公式: g(i,j) = α*f(i,j)+β  其中 α>0, β是增益变量
            byte g = changeContractAndBrightness(rgbaUchar[1]);//图像越亮,颜色值越往255靠近
            byte b = changeContractAndBrightness(rgbaUchar[2]);//对比度: 就是两个像素点之间的差值,差值越大对比度越高,反之越低
            byte dstUchar[] = {r, g, b, rgbaUchar[3]};
            mSrcUcharMat.put(row, col, dstUchar);

            //src float
            float rgbaFloat[] = new float[4];
            mat.get(row, col, rgbaFloat);
            float f_r = changeContractAndBrightness(rgbaFloat[0]);//用float计算会比uchar精度高一些,值会大一点点
            float f_g = changeContractAndBrightness(rgbaFloat[1]);
            float f_b = changeContractAndBrightness(rgbaFloat[2]);
            float dstFloat[] = {f_r, f_g, f_b, rgbaFloat[3]};
            mSrcFloatMat.put(row, col, dstFloat);

            //gray
            byte v[] = new byte[1];
            mGrayMat.get(row, col, v);
            byte pixel[] = new byte[1];
            pixel[0] = changeContractAndBrightness(v[0]);
            mGrayUcharMat.put(row, col, pixel);//灰度图也是一样的计算
        }
    }
    LogUtils.d("mydebug---", "time="+(System.currentTimeMillis()-start));//4579
    CV310Utils.mat2bitmapAndShowInIv(mSrcUcharMat, mSrcUcharBmp, mSrcUcharIv);
    Mat convert = new Mat();
    mSrcFloatMat.convertTo(convert, CvType.CV_8UC1);//src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4   matToBitmap只支持这几种type转换,所以需要把CV_32F再转成CV_8UC1
    CV310Utils.mat2bitmapAndShowInIv(convert, mSrcFloatBmp, mSrcFloatIv);//手机上由于转换的限制,float型的计算出的Mat无法直接显示,只能转成uchar,所以视觉上比ucahr变化不大
    CV310Utils.mat2bitmapAndShowInIv(mGrayUcharMat, mGrayUcharBmp, mGrayUcharIv);
}

/*初始化bitmap*/
private void initBitmaps(Bitmap bmp){
    mSrcUcharBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.RGB_565);
    mSrcFloatBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.RGB_565);
    mGrayBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.RGB_565);
    mGrayUcharBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.RGB_565);
}

//调整对比度与亮度,公式: g(i,j) = α*f(i,j)+β  其中 α>0, β是增益变量
//图像越亮,颜色值越往255靠近
//对比度: 就是两个像素点之间的差值,差值越大对比度越高,反之越低
private byte changeContractAndBrightness(byte color) {
    return (byte) CV310Utils.saturateCastUchar(alpha*CV310Utils.byte2unsignedchar(color) + beta);
}
private float changeContractAndBrightness(float color) {
    return CV310Utils.saturateCastUchar(alpha*color + beta);
}

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/80882605