java使用openCV处理图像入门教程

java使用openCV处理图像入门教程

1.第一步下载相应资源:
这里写图片描述
这里写图片描述
外网下载可能较慢,请耐心等待,或者试着挂一个vpn
下载完成进行安装,记住安装时选择的路径
2.导入在java项目中导入opencv的jar包
这里写图片描述
3.编写代码
这里写图片描述
把实现了我们在opencv中声明的native方法的那个library load进来,或者load其他什么动态连接库
4.运行代码
这里写图片描述
配置运行时jvm参数
这里写图片描述
path=自己的相应目录(64系统选择x64,32位系统选择x86),里头有一个dll文件

5.demo代码展示(涉及图像的饱和度,对比度,亮度调节,均值滤波,高斯滤波,图像去雾,图像转置,图像边缘检测,图像油画化):
—-github源代码连接——

package com.example.followwindd.util;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

import static org.opencv.core.Core.BORDER_DEFAULT;
import static org.opencv.core.Core.addWeighted;
import static org.opencv.core.Core.convertScaleAbs;
import static org.opencv.core.CvType.CV_16S;
import static org.opencv.imgproc.Imgproc.Sobel;
import static org.opencv.imgproc.Imgproc.cvtColor;

/**
 * 图像的基本处理函数
 *
 * @author 11633
 * @date 2018/4/20 21:29
 */
public class ImageUtil {


    public static final int MIN_VAL = 0;

    public static final int MAX_VAL = 255;

    public static final int BASE_VAL = (MIN_VAL + MAX_VAL) >>> 1;//大于中间值表示增强效果,小于中间值表示消减效果


    /**
     * 图像处理的基本功能
     */
    public static class Base {

        /**
         * @Description: 图像饱和度调节
         * @Param: Mat 传入的图像矩阵
         * @Param: val 调节系数
         * @Return: 调节完成的图像矩阵
         * @Author: followWindDog
         * @Date: 2018/4/18
         */
        public static Mat shiftSaturability(Mat mat, int val) {
            if (val == BASE_VAL) return mat;
            Mat hsv = new Mat();
            double f;
            boolean flag = false;
            if (val > BASE_VAL) {
                flag = true;
                f = 1.0 * (val - BASE_VAL) / BASE_VAL;
            } else {
                f = 1.0 * val / BASE_VAL;
            }

            Imgproc.cvtColor(mat, hsv, Imgproc.COLOR_BGR2HSV);

            for (int i = 0; i < hsv.height(); i++) {
                for (int j = 0; j < hsv.width(); j++) {
                    double[] vals = hsv.get(i, j);
                    if (flag) {
                        vals[1] = vals[1] + (MAX_VAL - vals[1]) * f;
                    } else {
                        vals[1] = vals[1] * f;
                    }
                    hsv.put(i, j, vals);
                }
            }
            Mat ret = new Mat();
            Imgproc.cvtColor(hsv, ret, Imgproc.COLOR_HSV2BGR);
            return ret;
        }

        /**
         * @Description: 图像的对比度调节
         * @Param: Mat 传入的图像矩阵
         * @Param: val 调节系数
         * @Return: 调节完成的图像矩阵
         * @Author: followWindDog
         * @Date: 2018/4/25
         */
        public static Mat shiftContrast(Mat img, int val) {
            if (val == BASE_VAL) return img;
            Mat ret = new Mat(img.height(), img.width(), img.type());
            double maxx = -1, minn = 300.0;
            for (int i = 0; i < img.height(); i++) {
                for (int j = 0; j < img.width(); j++) {
                    double[] vals = img.get(i, j);
                    for (int k = 0; k < vals.length; k++) {
                        maxx = maxx > vals[k] ? maxx : vals[k];
                        minn = minn < vals[k] ? minn : vals[k];
                    }
                }
            }
            double midd = (maxx + minn) / 2;
            double a;
            if(val>BASE_VAL){
                if(val==MAX_VAL)val--;
                a = BASE_VAL/(1.0*(MAX_VAL-val));
            }else{
                a = (1.0 * val) / BASE_VAL;
            }
            double b = midd * (1 - a);
            for (int i = 0; i < img.height(); i++) {
                for (int j = 0; j < img.width(); j++) {
                    double[] vals = img.get(i, j);
                    for (int k = 0; k < vals.length; k++) {
                        vals[k] = a * vals[k] + b;
                    }
                    ret.put(i, j, vals);
                }
            }
            return ret;
        }

        /**
         * @Description: 图像亮度调节
         * @Param: Mat 传入的图像矩阵
         * @Param: val 调节系数
         * @Return: 调节完成的图像矩阵
         * @Author: followWindDog
         * @Date: 2018/4/25
         */
        public static Mat shiftBrightness(Mat img, int val) {
            if (val == BASE_VAL)
                return img;
            Mat ret = new Mat(img.height(), img.width(), img.type());
            int hei = img.height();
            int wid = img.width();
            double f;
            boolean flag = false;
            if (val > BASE_VAL) {
                flag = true;
                f = 1.0 * (MAX_VAL - val) / BASE_VAL;
            } else {
                f = 1.0 * val / BASE_VAL;
            }
            for (int i = 0; i < hei; i++) {
                for (int j = 0; j < wid; j++) {
                    double[] vals = img.get(i, j);
                    for (int k = 0; k < vals.length; k++) {
                        if (flag) {
                            vals[k] = 255 - (vals[k] * f);
                        } else {
                            vals[k] = vals[k] * f;
                        }
                    }
                    ret.put(i, j, vals);
                }
            }
            return ret;
        }

        /**
         * @Description: 将矩阵进行转置
         * @Param: mat 要转置的图像矩阵
         * @Return: 转置过后的图像矩阵
         * @Author: followWindDog
         * @Date: 2018/4/18
         */
        public static Mat transposition(Mat mat) {
            Mat ret = new Mat(mat.width(), mat.height(), mat.type());
            for (int i = 0; i < mat.height(); i++) {
                for (int j = 0; j < mat.width(); j++) {
                    double[] vals = mat.get(i, j);
                    ret.put(j, i, vals);
                }
            }
            return ret;
        }
    }

    public static class Filter {

        private static int standardizeCellSize(int cellSize) {
            return cellSize % 2 == 0 ? cellSize + 1 : cellSize;
        }


        /**
         * @Description: 高斯函数
         * @Param: x 到达中心的x方向距离
         * @Param: y 到达中心的y方向距离
         * @Param: y 到达中心的y方向距离
         * @Return: variance 方差
         * @Author: followWindDog
         * @Date: 2018/4/20
         */
        private static double gaussianFunction(double x, double y, double variance) {
            return 1.0 / (2 * Math.PI * variance * variance) * Math.exp((-x * x - y * y) / (2 * variance * variance));
        }

        private static boolean chackRange(int i, int j, int hei, int wid) {
            return i >= 0 && i < hei && j >= 0 && j < wid;
        }

        private static Mat filtering(Mat mat, double[][] weightMatrix) {
            Mat ret = new Mat(mat.height(), mat.width(), mat.type());
            double[][][] m = new double[mat.height()][mat.width()][mat.get(0, 0).length];
            for (int i = 0; i < mat.height(); i++) {
                for (int j = 0; j < mat.width(); j++) {
                    m[i][j] = mat.get(i, j);
                }
            }

            int halfCellSize = weightMatrix.length >>> 1;
            int hei = mat.height();
            int wid = mat.width();
            for (int i = 0; i < hei; i++) {
                for (int j = 0; j < wid; j++) {
                    double[] suma = new double[3];
                    double sumb = 0;
                    for (int k = 0; k < weightMatrix.length; k++) {
                        for (int l = 0; l < weightMatrix.length; l++) {
                            int loci = i - (halfCellSize - k);
                            int locj = j - (halfCellSize - l);
                            if (chackRange(loci, locj, mat.height(), mat.width())) {
                                sumb += weightMatrix[k][l];
                                for (int n = 0; n < suma.length; n++) {
                                    suma[n] += weightMatrix[k][l] * m[loci][locj][n];
                                }
                            }
                        }
                    }
                    for (int k = 0; k < suma.length; k++) {
                        suma[k] /= sumb;
                    }
                    ret.put(i, j, suma);
                }
            }
            return ret;
        }

        public static Mat gaussianFiltering(Mat mat, int cellSize, double variance) {
            //通过高斯函数计算每一个格子的权值
            cellSize = standardizeCellSize(cellSize);
            int hCellSize = cellSize >>> 1;
            double[][] tCell = new double[cellSize][cellSize];
            double sum = 0;
            for (int i = 0; i < tCell.length; i++) {
                for (int j = 0; j < tCell[i].length; j++) {
                    tCell[i][j] = gaussianFunction(hCellSize - i, hCellSize - j, variance);
                    sum += tCell[i][j];
                }
            }
            for (int i = 0; i < tCell.length; i++) {
                for (int j = 0; j < tCell[i].length; j++) {
                    tCell[i][j] = tCell[i][j] * 100 / sum;
                }
            }
            return filtering(mat, tCell);
        }

        /**
         * @Description: 最普通的均值滤波
         * @Param: mat 要滤波的图像矩阵
         * @Param: cellSize 滤波方框的大小
         * @Return: 滤波完成后的矩阵
         * @Author: followWindDog
         * @Date: 2018/4/20
         */
        public static Mat averageFiltering(Mat mat, int cellSize) {
            //TODO 性能优化
            Mat ret = new Mat(mat.height(), mat.width(), mat.type());
            double[][][] mm = new double[mat.height()][mat.width()][mat.get(0, 0).length];
            for (int i = 0; i < mat.height(); i++) {
                for (int j = 0; j < mat.width(); j++) {
                    mm[i][j] = mat.get(i, j);
                }
            }
            cellSize = standardizeCellSize(cellSize);
            int halfCellSiz = cellSize >> 1;
            for (int i = 0; i < mat.height(); i++) {
                for (int j = 0; j < mat.width(); j++) {
                    double[] to = new double[3];
                    int fi = i - halfCellSiz, ti = i + halfCellSiz, fj = j - halfCellSiz, tj = j + halfCellSiz;
                    for (int k = 0; k < to.length; k++) {
                        double sum = 0;
                        int cnt = 0;
                        for (int l = fi; l <= ti; l++) {
                            for (int m = fj; m <= tj; m++) {
                                if (l >= 0 && l < mat.height() && m >= 0 && m < mat.width()) {
                                    sum += mm[l][m][k];
                                    cnt++;
                                }
                            }
                        }
                        to[k] = sum / cnt;
                    }
                    ret.put(i, j, to);
                }
            }
            return ret;
        }

        /**
         * @Description: 将图片进行锐化
         * @Param: mat 传入的图像矩阵
         * @Param: cellSize 滤波使用的方框大小
         * @Param: factor 锐化强度
         * @Return: 锐化过后的矩阵
         * @Author: followWindDog
         * @Date: 2018/4/18
         */
        public static Mat sharpen(Mat mat, int cellSize, int factor) {
            Mat filter = averageFiltering(mat, cellSize);
            Mat ret = new Mat(mat.height(), mat.width(), mat.type());
            for (int i = 0; i < ret.height(); i++) {
                for (int j = 0; j < ret.width(); j++) {
                    double[] rgb = mat.get(i, j);
                    double[] frgb = filter.get(i, j);
                    for (int k = 0; k < rgb.length; k++) {
                        rgb[k] += factor * (rgb[k] - frgb[k]);
                    }
                    ret.put(i, j, rgb);
                }
            }
            return ret;
        }

        /*
        * 求图像的暗通道
        * */
        private static double[][] getDarkChannel(Mat mat, int cellSize) {
            if (cellSize % 2 == 0)
                cellSize++;
            int hcellSize = cellSize >>> 1;
            double[][] doubles = new double[mat.height()][mat.width()];
            for (int i = 0; i < mat.height(); i++) {
                for (int j = 0; j < mat.width(); j++) {
                    double[] vals = mat.get(i, j);
                    doubles[i][j] = vals[0];
                    for (int k = 1; k < vals.length; k++) {
                        doubles[i][j] = (doubles[i][j] < vals[k]) ? doubles[i][j] : vals[k];
                    }
                }
            }

            double[][] ret = new double[mat.height()][mat.width()];
            for (int i = 0; i < mat.height(); i++) {
                for (int j = 0; j < mat.width(); j++) {
                    double maxx = 300;
                    for (int k = 0; k < cellSize; k++) {
                        for (int l = 0; l < cellSize; l++) {
                            int locx = i + (k - hcellSize);
                            int locy = j + (l - hcellSize);
                            if (locx >= 0 && locx < ret.length && locy >= 0 && locy < ret[locx].length)
                                maxx = (maxx < doubles[locx][locy]) ? maxx : doubles[locx][locy];
                        }
                    }
                    ret[i][j] = maxx;
                }
            }
            return ret;
        }



        /**
         * @Description: 图像进行去雾处理(何凯铭去雾)
         * @Param: mat 等待去雾的图像
         * @Param: cellSize 去雾时使用的方框大小
         * @Return: 去雾完成的图像
         * @Author: followWindDog
         * @Date: 2018/4/25
         */
        public static Mat disFog(Mat mat, int cellSize) {
            double[][] dackCha = getDarkChannel(mat, cellSize);
            Mat ret = new Mat(mat.height(), mat.width(), mat.type());

            for (int i = 0; i < ret.height(); i++) {
                for (int j = 0; j < ret.width(); j++) {
                    double[] valsTo = new double[3];
                    double[] valsFrom = mat.get(i, j);
                    double f = dackCha[i][j] / 255;
                    for (int k = 0; k < valsFrom.length; k++) {
                        valsTo[k] = (valsFrom[k] - 127 * f) / (1 - f);
                    }
                    ret.put(i, j, valsTo);
                }
            }
            return ret;
        }



        /**
         * @Description: 为图像进行边缘检测
         * @Param: img 等待边缘检测的图像矩阵
         * @Return: 表示图像边缘的矩阵
         * @Author: followWindDog
         * @Date: 2018/4/25
         */
        public static Mat edgeDetection(Mat img) {
            Mat clone = img.clone();
            int sizex = 5, sizey = 5;
            double dx = 0, dy = 0;
            Imgproc.GaussianBlur(clone, clone, new Size(sizex, sizey), dx, dy, BORDER_DEFAULT);
            Mat grad_x = new Mat(), grad_y = new Mat(), src_gray = new Mat();
            Mat abs_grad_x = new Mat(), abs_grad_y = new Mat();
            cvtColor(clone, src_gray, Imgproc.COLOR_BGR2GRAY);
            int scale = 1;
            int delta = 0;
            int ddepth = CV_16S;
            Sobel(src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT);
            convertScaleAbs(grad_x, abs_grad_x);

            Sobel(src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT);
            convertScaleAbs(grad_y, abs_grad_y);
            Mat ret = new Mat();
            addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, ret);
            return ret;
        }



        /**
         * @Description: 为图像添加类似油画的效果
         * @Param: img 等待处理的图像
         * @Return: 经过油画处理的图像
         * @Author: followWindDog
         * @Date: 2018/4/25
         */
        public static Mat oilPainting(Mat img) {

            Mat mat1 = edgeDetection(img);
            Imgproc.GaussianBlur(img, img, new Size(11, 11), 20, 20, Core.BORDER_DEFAULT);
            for (int i = 0; i < img.height(); i++) {
                for (int j = 0; j < img.width(); j++) {
                    double[] doubles = img.get(i, j);
                    double[] doubles1 = mat1.get(i, j);
                    for (int k = 0; k < doubles.length; k++) {
                        doubles[k] -= 1 * doubles1[0];
                    }
                    img.put(i, j, doubles);
                }
            }
            return img;
        }

    }
}

测试代码

package com.example.followwindd.test;

import com.example.followwindd.util.ImageUtil;
import org.junit.Test;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;


/**
 * @author 11633
 * @date 2018/4/21 8:46
 */
public class TestImageUtil {
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    private static Mat imread = Imgcodecs.imread("./photo/00005.jpg");

    public static void showImg(Mat imread, int len) {
        HighGui.namedWindow("test", HighGui.WINDOW_AUTOSIZE);
        HighGui.imshow("test", imread);
        HighGui.waitKey(len);
    }

    public static class TestBase {
        @Test
        public void testShiftSaturability() {
            for (int i = 0; i <= 255; i += 50)
                showImg(ImageUtil.Base.shiftSaturability(imread, i), 1000);
        }

        @Test
        public void testShiftContrast() {
            for (int i = 0; i <= 255; i += 50)
                showImg(ImageUtil.Base.shiftContrast(imread, i), 1000);
        }

        @Test
        public void testShiftBrightness() {
            for (int i = 0; i <= 255; i += 50) {
                showImg(ImageUtil.Base.shiftBrightness(imread, i), 1000);
            }
        }

        @Test
        public void testTransposition() {
            showImg(ImageUtil.Base.transposition(imread), 0);
        }
    }


    public static class TestFilter {
        @Test
        public void testGaussianFiltering() {
            for (int i = 3; i < 20; i += 2) {
                showImg(ImageUtil.Filter.gaussianFiltering(imread, i, 100), 100);
                System.out.println(i);
            }
        }


        @Test
        public void testAverageFiltering() {
            for (int i = 3; i < 20; i += 2) {
                showImg(ImageUtil.Filter.averageFiltering(imread, i), 100);
                System.out.println(i);
            }
        }

        @Test
        public void testSharpen() {
            for (int i = 3; i < 20; i += 2) {
                showImg(ImageUtil.Filter.sharpen(imread, i, 2), 100);
                System.out.println(i);
            }
        }

        @Test
        public void testDisFog() {
            showImg(ImageUtil.Filter.disFog(imread, 20), 0);
        }

        @Test
        public void testEdgeDetection() {
            showImg(ImageUtil.Filter.edgeDetection(imread), 0);
        }


        @Test
        public void testOilPainting() {
            showImg(ImageUtil.Filter.oilPainting(imread), 0);
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值