波段运算支持四则运算(加减乘除)

news/2024/7/21 4:10:02 标签: 图像处理

Qt、GDAL遥感影像显示

1、创建类

class GisBandMathProcess
	: public GisRasterProcess
{
	OGIS_DECLARE_MEMBERS(GisBandMathProcess);
public:

	GisBandMathProcess();

	~GisBandMathProcess();

	virtual QString processName() const;

	virtual OGis::ErrorStatus beginProcess();

	virtual OGis::ErrorStatus processData(ProcessData *pData) const;

	virtual OGis::ErrorStatus process(MatArray &desMat, const MatArray &srcMat, const MatArray &maskArray = MatArray());

private:

	void parseExperssion();

private:

	uint m_datasetIndex;
	QString m_exp, m_sPath;
	UIntArray m_bandIndexs;
	QStringList m_expStrings;

};

2、实现类

#include "StdAfx.h"

OGIS_CONS_DEFINE_MEMBERS_WORKER(GisBandMathProcess, GisRasterProcess)

GisBandMathProcess::GisBandMathProcess()
	: GisRasterProcess()
{

}

GisBandMathProcess::~GisBandMathProcess()
{

}

void GisBandMathProcess::parseExperssion()
{
	QString expStr(m_exp);
	QRegularExpression regExp("B|b[0-9]");
	QRegularExpressionMatch match;
	do {
		match = regExp.match(expStr);
		if(match.hasMatch()) {
			QString band = match.captured();
			QString tagName = QS("%1").arg(band);
			m_expStrings.append(tagName);
			expStr.remove(band, Qt::CaseInsensitive);
		}
		else {
			break;
		}
	} while(true);
}

QString GisBandMathProcess::processName() const
{
	return QS("波段运算");
}

OGis::ErrorStatus GisBandMathProcess::beginProcess()
{
	GisBandMathDialog dialog;
	if(QDialog::Rejected == dialog.exec()) {
		return OGis::eUserCancel;
	}
	m_exp = dialog.bandMathExp().trimmed().toLower();
	if(m_exp.isEmpty()) {
		return OGis::eInvalidString;
	}
	parseExperssion();
	GisVariableToBandsPairings varDialog;
	varDialog.setExpression(m_exp);
	varDialog.adjustSize();
	if(QDialog::Rejected == varDialog.exec()) {
		return OGis::eUserCancel;
	}
	m_sPath = varDialog.getSaveFileName();
	varDialog.getBandsPairing(m_datasetIndex, m_bandIndexs);
	return GisRasterProcess::beginProcess();
}

double GetMatValue(const cv::Mat &src, int row, int col)
{
	int type = src.type();
	switch(type) {
		case CV_8U: return (double)src.at<byte>(row, col);
		case CV_8S: return (double)src.at<char>(row, col);
		case CV_16U: return (double)src.at<ushort>(row, col);
		case CV_16S: return (double)src.at<short>(row, col);
		case CV_32S: return (double)src.at<int>(row, col);
		case CV_32F: return (double)src.at<float>(row, col);
		case CV_64F: return (double)src.at<double>(row, col);
		default:
			break;
	}
	return 0;
}

OGis::ErrorStatus GisBandMathProcess::processData(ProcessData *pData) const
{
	if(nullptr == pData) {
		return OGis::eNullObjectPointer;
	}
	RasterData *mpRasterData = (RasterData *)pData;
	mpRasterData->bDisplay = true;
	mpRasterData->datasetIndex = m_datasetIndex;
	mpRasterData->exportDataType = 7;
	mpRasterData->oFormat = OGis::kEnvi;
	mpRasterData->blockSize = {1024, 1024};
	mpRasterData->itemArray = m_bandIndexs;
	mpRasterData->outputFileName = m_sPath;
	mpRasterData->resultSize = {0, 0, 1};
	pData = mpRasterData;
	return OGis::eOk;
}

OGis::ErrorStatus GisBandMathProcess::process(MatArray &desMat, const MatArray &srcMat, const MatArray &maskArray)
{
	QJSEngine myEngine; int rows = srcMat[0].rows, cols = srcMat[0].cols;
	GisProgressBarPointer progressBar(QS("[%1]").arg(m_exp), rows, true);
	cv::Mat des = cv::Mat(rows, cols, CV_64FC1);
	for(int row = 0; row < rows; ++row) {
		progressBar.setProgressPos(row);
		for(int col = 0; col < cols; ++col) {
			QString exp = m_exp; bool bCal = true;
			for(int idx = 0; idx < srcMat.size(); ++idx) {
				cv::Mat mat = srcMat[idx]; double val = 0;
				if(maskArray.size() > 0) {
					cv::Mat mask = maskArray[idx];
					val = GetMatValue(mask, row, col);
					bCal = bCal && (val != 0);
				}
				val = GetMatValue(mat, row, col);
				exp.replace(m_expStrings[idx], QS("%1").arg(val));
			}
			if(bCal) {
				double val = myEngine.evaluate(exp).toNumber();
				des.at<double>(row, col) = val;
			}
			else {
				des.at<double>(row, col) = nan("");
			}
		}
	}
	desMat << des;
	return OGis::eOk;
}

GisBandMathDialog:波段运算表达式输出对话框;

GisVariableToBandsPairings:定义波段运算中(b1,b2,b3)变量对应的波段;

processData(ProcessData *pData) 接口中具体参数如下:

mpRasterData->bDisplay = true;                                     //处理结果自动打开
mpRasterData->datasetIndex = m_datasetIndex;         //数据集处理的索引
mpRasterData->exportDataType = 7;                             //输出数据的类型
mpRasterData->oFormat = OGis::kEnvi;                       //结果数据保存为ENVI格式
mpRasterData->blockSize = {1024, 1024};                     //数据处理分块大小
mpRasterData->itemArray = m_bandIndexs;                //数据处理的波段
mpRasterData->outputFileName = m_sPath;                //结果数据保存的全路径
mpRasterData->resultSize = {0, 0, 1};                            //结果数据的大小(0:为原始数据大小)

接口 process(MatArray &desMat, const MatArray &srcMat, const MatArray &maskArray) 是数据处理的核心:

利用Qt提供的QJSEngine类(支持四则运算),所以我们将波段表达式中的b1,b2,b3等参数进行像素值替换。例如:计算NDVI = (b1-b2)/(b1+b2)。b1是近红外波段,b2是红波段,我们将b1和b2替换成对应波段的像素值,即表达式为:(24-62)/(24+62),然后通过double val = myEngine.evaluate(exp).toNumber(); 计算结果为:-0.4418,这个值也就是对应输出结果影像的像素值。


http://www.niftyadmin.cn/n/5310402.html

相关文章

【WPF】使用 WriteableBitmap 提升 Image 性能

【WPF】使用 WriteableBitmap 提升 Image 性能 前言WriteableBitmap 背景WriteableBitmap 渲染原理WriteableBitmap 使用技巧案例核心源码测试结果 前言 由于中所周不知的原因&#xff0c;WPF 中想要快速的更新图像的显示速率一直以来都是一大难题。在本文中&#xff0c;我将分…

程序员面试:从新手到高手的成长之路

面试是程序员职业生涯中不可或缺的一环。对于新手程序员来说&#xff0c;掌握一些必备的面试技巧&#xff0c;有助于在面试中脱颖而出&#xff0c;快速成长为高手。本文将分享一些面试经历和面试技巧&#xff0c;帮助你更好地应对面试挑战。 一、面试经历分享 在分享技巧之前…

计算机毕业设计——基于SSM+Layui的图书管理系统(附源码)

1&#xff0c;项目背景 国家大力推进信息化建设的大背景下&#xff0c;城市网络基础设施和信息化应用水平得到了极大的提高和提高。特别是在经济发达的沿海地区&#xff0c;商业和服务业也比较发达&#xff0c;公众接受新事物的能力和消费水平也比较高。开展商贸流通产业的信息…

网络视频监控和流媒体技术-基础知识整理

经常有人问我网络视频监控上的一些基本概念&#xff0c;以及流媒体技术相关的一些概念和基础知识&#xff0c;这里整理一下&#xff0c;与大家分享。现在先整理这么多&#xff0c;可能还有不少没有&#xff0c;大家可以提出意见&#xff0c;我再加进去。 1&#xff09;OSI 参考…

python 人脸检测与人脸识别

安装库文件: pip install dlib face_recognition import dlib import face_recognition import cv2 from PIL import Image, ImageDraw# 判断运行环境 cpu or gpu def check_env():print(dlib.DLIB_USE_CUDA)print(dlib.cuda.get_num_devices())# 判断人脸在图片当中的位置 def…

javascript 常见工具函数(三)

21.克隆数组的几种方法&#xff1a; &#xff08;1&#xff09;slice方法&#xff1a; let arr [1,2,3,4] let arr1 arr.slice() //或者是 let arr1 arr.slice(0) arr[0] 6 console.log(arr) // [6, 2, 3, 4] console.log(arr1) // [1, 2, 3, 4] &#xff08;2&…

k8s的yaml文件中的kind类型都有哪些?(清单版本)

在操作kubenates的过程中&#xff0c;我们接触到的yaml文件中的kind类型有很多。他们代表了kubenate的不同类型的对象&#xff0c;了解了kind的类型&#xff0c;也就相当于了解了k8s都有哪些类型的对象。 类型清单及概要说明 序号类型简述1Pod一个Kubernetes中最基本的资源类型…

JSON Crack数据可视化工具结合内网穿透实现公网访问

文章目录 1. 在Linux上使用Docker安装JSONCrack2. 安装Cpolar内网穿透工具3. 配置JSON Crack界面公网地址4. 远程访问 JSONCrack 界面5. 固定 JSONCrack公网地址 JSON Crack 是一款免费的开源数据可视化应用程序&#xff0c;能够将 JSON、YAML、XML、CSV 等数据格式可视化为交互…