环境:IDEA2021.2.3+jdk11.0.1+GDAL(release-1928-x64-gdal-3-5-2-mapserver-8-0-0)+OpenCV-460.jar

一、OpenCV中的Mat类

1.定义及使用方法:

Mat可以保存图片,根据所读入的图片为其分配相应大小的内存空间 ,也能利用构造方法自己定义,下面是两种创建方法:

Mat mat1 = new Mat(2,2, CvType.CV_8UC3);
Mat mat2 = Imgcodecs.imread("img\\5.png");

让我们用println()试一试打印mat会出现什么?

System.out.println(mat1);
System.out.println(mat2);

结果:

伪彩色图转换为灰度 python 伪彩色合成的教程_opencv

 这些代表什么意思呢?

2*2*CV_8UC3:2像素×2像素×数据类型
isCont:是否联系存储
isSubmat:是否为子矩阵
nativeObj:本地对象地址
dataAddr:存储的图片的地址

那么数据类型包括哪些呢?如图(图片来源于CSDN@UU果),中间的数字为各种数据类型所对应的整数

解释:2*2*CV_8UC3 中下划线后的数字表示位数、数字后的第一个字母表示用于储存像素的类型、后面的符号表示通道数

U:unsigned int ,无符号整型

S:signed int ,有符号整型

F:float,单精度浮点型,float类型本身即有符号

Cx:图像的通道数

伪彩色图转换为灰度 python 伪彩色合成的教程_伪彩色图转换为灰度 python_02

 接下来我们看看Mat怎样存储的像素

System.out.println(mat1.dump());
System.out.println(mat2.dump());

伪彩色图转换为灰度 python 伪彩色合成的教程_java_03

我们所定义的大小是 2行2列,2列就是两个矩形框,每一列都包括B,G,R三个通道

伪彩色图转换为灰度 python 伪彩色合成的教程_图像处理_04

 我们之前所输出的信息为20行18列,18列总共有54个通道数,因为图片大小有限,仅展示行数

现在我们清楚了Mat类的存储格式,来看看伪彩色图像是怎么生成的。

二、实现过程

原理:将单波段的灰度值分级赋予不同的颜色,例如,将灰度值为0-85的赋予B蓝色通道,86-170的赋予G绿色通道,171-255的赋予R红色通道,(怎么分级可按具体情况自己决定),其余两个通道均赋予0值

import org.gdal.gdal.Band;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;

/**
 * @Author: HNUST_jue_chen
 * @Date: 2022/10/22/ 9:44
 * @Attention: 转载, 引用请注明出处
 */

//伪彩色合成
public class CalPseudoColor {
    //加载本地动态链接库
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    public void graySplit(String path) {

        try {

            gdal.AllRegister();//支持所有驱动
            //以只读方式读取数据存入Dataset类型里
            Dataset dataset = gdal.Open(path, gdalconstConstants.GA_ReadOnly);
            //图像的大小
            int iYSize = dataset.getRasterYSize();
            int iXSize = dataset.getRasterXSize();
            //获取图像的灰度波段
            Band band = dataset.GetRasterBand(1);
            //定义灰度值数组
            int[][] bandArr = new int[iYSize][iXSize];
            //将图像灰度值存入灰度值数组
            for (int i = 0; i < bandArr.length; i++) {
                band.ReadRaster(0, i, iXSize, 1, bandArr[i]);  //一次读取一行灰度值数据
            }

            //灰度图的伪彩色合成(密度分割)
            //OpenCV三通道存储图像的像素是按照B,G,R顺序存储的
            //单通道转多通道算法:
            //原图像灰度值为0-85的赋予B蓝色通道,86-170的赋予G绿色通道,171-255的赋予R红色通道,其余两个通道均赋予0
            //定义二维数组存储三通道的像素值
            int[][] bandArrThreeChannel = new int[iYSize][iXSize * 3];
            for (int i = 0; i < iYSize; i++) {
                for (int j = 0; j < iXSize; j++) {
                    if (bandArr[i][j] >= 170) {
                        //灰度值为171-255的赋予红色通道,其余两个通道赋予0
                        bandArrThreeChannel[i][3 * j + 2] = bandArr[i][j];
                        bandArrThreeChannel[i][3 * j] = 0;
                        bandArrThreeChannel[i][3 * j + 1] = 0;
                    } else if (bandArr[i][j] >= 85) {
                        //灰度值为86-170的赋予绿色通道,其余两个通道赋予0
                        bandArrThreeChannel[i][3 * j + 1] = bandArr[i][j];
                        bandArrThreeChannel[i][3 * j] = 0;
                        bandArrThreeChannel[i][3 * j + 2] = 0;
                    } else if (bandArr[i][j] >= 0) {
                        //灰度值为0-85的赋予蓝色通道,其余两个通道赋予0
                        bandArrThreeChannel[i][3 * j] = bandArr[i][j];
                        bandArrThreeChannel[i][3 * j + 1] = 0;
                        bandArrThreeChannel[i][3 * j + 2] = 0;
                    }
                }
            }

            //定义伪彩色图像的大小及数据类型
            //CV_32SC3:32表示32位,S表示有符号整型,C3表示3个通道
            Mat img_cpc = new Mat(bandArr.length, bandArr[0].length, CvType.CV_32SC3);
            for (int i = 0; i < bandArrThreeChannel.length; i++) {
                img_cpc.put(i, 0, bandArrThreeChannel[i]);  //一次放入一行三通道像素值数据
            }

            //存储伪彩色图像
            Imgcodecs.imwrite("D:\\Project\\IDEA_Project\\RS01\\src\\rs01\\img\\2_cpc.png", img_cpc);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        CalPseudoColor img_gray = new CalPseudoColor();
        img_gray.graySplit("D:\\Project\\IDEA_Project\\RS01\\src\\rs01\\img\\2_gray.png");
    }
}

 三、结果

输入的灰度图像为:

伪彩色图转换为灰度 python 伪彩色合成的教程_java_05

输出为伪彩色图像为:

伪彩色图转换为灰度 python 伪彩色合成的教程_opencv_06