学习笔记:从0开始学习大数据-23. R语言recharts,REMap案例

本文通过三个实例展示了如何使用R语言进行地理数据的可视化,包括地图块、热力图及迁移图的绘制过程,适用于数据分析师和技术人员学习和参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下学习的三个例子均copy自网络,调试运行后的代码和运行结果复制如下,以备后用。

一、地图块

library(ggplot2)
library(baidumap)
library(ggmap)
options(baidumap.key = 'XXX')
q <- getBaiduMap('广州白云山', width=600, height=600, zoom=18, scale = 2, messaging=FALSE)
ggmap(q) 

二、热力图

library(REmap)
options(remap.js.web=T)
data<- read.csv(file="/home/linbin/文档/R/cityvaluetop10.csv",header=T)
theme1 <- get_theme(theme = "none",
                    lineColor = "white",
                    backgroundColor = "white", 
                    titleColor = "#fff",
                    borderColor = "blue", 
                    regionColor = "grey",
                    labelShow = T, 
                    pointShow = F, 
                    pointColor = "gold")
remapH(data,
       maptype = 'china',
       theme = theme1,
       blurSize = 70,
       color = "red",
       minAlpha = 10,
       opacity = 1,)

cityvaluetop10.csv 文件数据格式

lon,lat,prob
114.394818,23.408004,0.85
110.50664,28.695864,0.8
112.920664,26.695864,0.8
112.720664,26.695864,0.8
113.487804,34.157184,0.75
...

三、迁移图

library(ggplot2)
library(baidumap)
library(REmap)
library(ggmap)
options(baidumap.key = 'XXX')
options(remap.ak = "XXX")
#get_city_coord("天津")
#city_list <- c("beijing","tianjin","hefei","suzhou","chongqing")
#get_geo_position(city_list)
destination<- c("beijing","tianjin","nanjing","hefei","chengdu")    #终点
origin<- rep("guangzhou",length(destination)) 
map_data<- data.frame(origin,destination)
head(map_data)
map_out<-remap(mapdata=map_data,   #流向地图的数据源(依次为起点、终点两列)
               title="我是标题",         #设置主标题
               subtitle="我是副标题",    #设置副标题
               theme =get_theme(theme="Sky")) #设置主题(默认主题一共有三套:“Dark”,“Bright,”Sky“)
plot(map_out)

<think>根据提供的两幅图像的投影矩阵(3x4矩阵),我们可以恢复相机的内参矩阵K和外参矩阵[R|t]。投影矩阵P可以分解为K[R|t]。由于我们有两个投影矩阵P1和P2,我们可以通过分解和相对位姿计算来得到立体校正所需的参数。 步骤: 1. 将给定的投影矩阵P1和P2分别分解为内参矩阵K1、K2和旋转矩阵R1、R2以及平移向量t1、t2。 2. 计算两个相机之间的相对位姿:R = R2 * R1^T, t = t2 - R * t1。 3. 使用stereoRectify函数进行立体校正。 注意:由于投影矩阵可能包含尺度因子,分解时需要注意。OpenCV中可以使用decomposeProjectionMatrix函数进行分解。 代码实现: ```cpp #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { // 图像路径 string img1_path = "D:/data1/data1/015AR027.tif"; string img2_path = "D:/data1/data1/015AR028.tif"; string output_dir = "D:/data1/output/"; // 加载图像 Mat img1 = imread(img1_path, IMREAD_COLOR); Mat img2 = imread(img2_path, IMREAD_COLOR); if (img1.empty() || img2.empty()) { cerr << "错误:无法加载图像!" << endl; return -1; } Size originalSize = img1.size(); // 定义投影矩阵P1和P2(3x4) Mat P1 = (Mat_<double>(3, 4) << -12179.8753230552230, 7050.9952897638232, -2467.7527210258945, -17321440031.6463700000000, 4723.7392252925192, 5779.0243267188052, -11880.0042304789190, -22040783539.2805860000000, -0.4907881086633, -0.5142398041434, -0.7033380810316, 2000536.1381758042000); Mat P2 = (Mat_<double>(3, 4) << -12158.6697497674500, 7092.3578385200199, -2453.7545028069599, -17474815958.9305270000000, 4621.9021026258170, 5524.7193480639962, -12039.9681076173220, -21127026467.7189250000000, -0.5027584877552, -0.5235467256044, -0.6878464429645, 2038373.8802346450000); // 分解投影矩阵 Mat K1, R1, T1; int flag1 = 0; Mat K2, R2, T2; int flag2 = 0; // 使用decomposeProjectionMatrix decomposeProjectionMatrix(P1, K1, R1, T1); decomposeProjectionMatrix(P2, K2, R2, T2); // 注意:decomposeProjectionMatrix返回的T是4x1的向量(齐次坐标),需要转换为非齐次 T1 = T1.rowRange(0,3) / T1.at<double>(3); T2 = T2.rowRange(0,3) / T2.at<double>(3); // 计算相对位姿:从相机1到相机2 Mat R = R2 * R1.t(); // R2 * R1^T Mat t = T2 - R * T1; // 输出变量 Mat R1_rect, R2_rect, P1_rect, P2_rect, Q; // 进行立体校正 stereoRectify(K1, Mat(), K2, Mat(), originalSize, R, t, R1_rect, R2_rect, P1_rect, P2_rect, Q, 0, -1, originalSize); // 使用alpha=-1保留所有像素 // 计算校正映射 Mat map1x, map1y, map2x, map2y; initUndistortRectifyMap(K1, Mat(), R1_rect, P1_rect, originalSize, CV_32FC1, map1x, map1y); initUndistortRectifyMap(K2, Mat(), R2_rect, P2_rect, originalSize, CV_32FC1, map2x, map2y); // 应用校正映射 Mat rectified1, rectified2; remap(img1, rectified1, map1x, map1y, INTER_LINEAR, BORDER_CONSTANT, Scalar()); remap(img2, rectified2, map2x, map2y, INTER_LINEAR, BORDER_CONSTANT, Scalar()); // 保存校正后的图像 imwrite(output_dir + "rectified_left.jpg", rectified1); imwrite(output_dir + "rectified_right.jpg", rectified2); // 显示结果 namedWindow("校正左图", WINDOW_NORMAL); imshow("校正左图", rectified1); namedWindow("校正右图", WINDOW_NORMAL); imshow("校正右图", rectified2); waitKey(0); cout << "核线校正影像已生成,保存在:" << output_dir << endl; return 0; } ``` ### 关键步骤说明: 1. **投影矩阵分解**:使用`decomposeProjectionMatrix`分解投影矩阵得到内参矩阵K、旋转矩阵R和平移向量T(注意返回的T是齐次坐标,需要转换)。 2. **相对位姿计算**:计算从第一个相机到第二个相机的相对旋转R和平移t。 3. **立体校正**:使用`stereoRectify`计算校正变换,这里我们设置alpha=-1,以保留所有原始像素(可能会包含黑色区域)。 4. **重映射**:根据校正映射对原始图像进行重映射。 ### 注意事项: - 由于投影矩阵可能不是标准形式,分解后得到的内参矩阵K可能需要归一化(例如,将最后一行除以前两行的尺度),但OpenCV的`decomposeProjectionMatrix`已经处理了这一点。 - 如果图像尺寸很大,可能需要调整窗口大小或使用图像金字塔来加速处理。 §§相关问题§§ 1. 如果投影矩阵分解失败,OpenCV的decomposeProjectionMatrix函数会返回什么?如何检测分解的有效性? 2. 在计算相对位姿时,为什么使用R = R2 * R1.t()和t = T2 - R * T1? 3. 当立体校正后图像出现严重变形时,可能的原因是什么?如何调整? 4. 对于大尺寸遥感图像,如何优化核线校正的计算速度和内存占用? 5. 如何验证生成的核线影像是否满足极线约束?有哪些可视化方法?</think>根据您提供的投影矩阵,我将重新生成核线校正代码。这些投影矩阵包含相机的完整位姿信息,无需单独提供相机内参和外参。以下是完整的实现方案: ```cpp #include <opencv2/opencv.hpp> #include <iostream> #include <cmath> using namespace cv; using namespace std; int main() { // 图像路径 string img1_path = "D:/data1/data1/015AR027.tif"; string img2_path = "D:/data1/data1/015AR028.tif"; string output_dir = "D:/data1/output/"; // 加载图像 Mat img1 = imread(img1_path, IMREAD_COLOR); Mat img2 = imread(img2_path, IMREAD_COLOR); if (img1.empty() || img2.empty()) { cerr << "错误:无法加载图像!" << endl; return -1; } Size imgSize = img1.size(); // 定义投影矩阵P1和P2 (3×4) Mat P1 = (Mat_<double>(3, 4) << -12179.8753230552230, 7050.9952897638232, -2467.7527210258945, -17321440031.6463700000000, 4723.7392252925192, 5779.0243267188052, -11880.0042304789190, -22040783539.2805860000000, -0.4907881086633, -0.5142398041434, -0.7033380810316, 2000536.1381758042000); Mat P2 = (Mat_<double>(3, 4) << -12158.6697497674500, 7092.3578385200199, -2453.7545028069599, -17474815958.9305270000000, 4621.9021026258170, 5524.7193480639962, -12039.9681076173220, -21127026467.7189250000000, -0.5027584877552, -0.5235467256044, -0.6878464429645, 2038373.8802346450000); // 从投影矩阵恢复相机参数 Mat K1, R1, t1; decomposeProjectionMatrix(P1, K1, R1, t1); t1 = t1.rowRange(0, 3) / t1.at<double>(3); // 转换为3×1向量 Mat K2, R2, t2; decomposeProjectionMatrix(P2, K2, R2, t2); t2 = t2.rowRange(0, 3) / t2.at<double>(3); // 转换为3×1向量 // 计算相对位姿 Mat R = R2 * R1.t(); Mat t = t2 - R * t1; // 输出变量 Mat R1_rect, R2_rect, P1_rect, P2_rect, Q; // ========== 1. 生成水平核线影像 ========== stereoRectify(K1, Mat(), K2, Mat(), imgSize, R, t, R1_rect, R2_rect, P1_rect, P2_rect, Q, CALIB_USE_INTRINSIC_GUESS, 0, imgSize); Mat map1x, map1y, map2x, map2y; initUndistortRectifyMap(K1, Mat(), R1_rect, P1_rect, imgSize, CV_32FC1, map1x, map1y); initUndistortRectifyMap(K2, Mat(), R2_rect, P2_rect, imgSize, CV_32FC1, map2x, map2y); Mat rectified1_horizontal, rectified2_horizontal; remap(img1, rectified1_horizontal, map1x, map1y, INTER_LINEAR, BORDER_CONSTANT, Scalar()); remap(img2, rectified2_horizontal, map2x, map2y, INTER_LINEAR, BORDER_CONSTANT, Scalar()); imwrite(output_dir + "horizontal_left.jpg", rectified1_horizontal); imwrite(output_dir + "horizontal_right.jpg", rectified2_horizontal); // ========== 2. 生成垂直核线影像 ========== Mat rectified1_vertical, rectified2_vertical; rotate(rectified1_horizontal, rectified1_vertical, ROTATE_90_CLOCKWISE); rotate(rectified2_horizontal, rectified2_vertical, ROTATE_90_CLOCKWISE); imwrite(output_dir + "vertical_left.jpg", rectified1_vertical); imwrite(output_dir + "vertical_right.jpg", rectified2_vertical); // ========== 3. 生成最接近原始的核线影像 ========== stereoRectify(K1, Mat(), K2, Mat(), imgSize, R, t, R1_rect, R2_rect, P1_rect, P2_rect, Q, CALIB_USE_INTRINSIC_GUESS, -1, imgSize); initUndistortRectifyMap(K1, Mat(), R1_rect, P1_rect, imgSize, CV_32FC1, map1x, map1y); initUndistortRectifyMap(K2, Mat(), R2_rect, P2_rect, imgSize, CV_32FC1, map2x, map2y); Mat rectified1_closest, rectified2_closest; remap(img1, rectified1_closest, map1x, map1y, INTER_LINEAR, BORDER_CONSTANT, Scalar()); remap(img2, rectified2_closest, map2x, map2y, INTER_LINEAR, BORDER_CONSTANT, Scalar()); imwrite(output_dir + "closest_left.jpg", rectified1_closest); imwrite(output_dir + "closest_right.jpg", rectified2_closest); // 显示结果 namedWindow("水平核线影像", WINDOW_NORMAL); imshow("水平核线影像", rectified1_horizontal); namedWindow("垂直核线影像", WINDOW_NORMAL); imshow("垂直核线影像", rectified1_vertical); namedWindow("最接近原始影像", WINDOW_NORMAL); imshow("最接近原始影像", rectified1_closest); waitKey(0); cout << "已生成三种类型的核线影像,保存在:" << output_dir << endl; return 0; } ``` ### 关键步骤说明: 1. **投影矩阵处理**: - 使用`decomposeProjectionMatrix`从给定的3×4投影矩阵中提取相机内参(K)、旋转矩阵(R)和平移向量(t) - 将齐次坐标转换为3×1平移向量 2. **相对位姿计算**: ```cpp Mat R = R2 * R1.t(); // 相对旋转矩阵 Mat t = t2 - R * t1; // 相对平移向量 ``` 3. **立体校正流程**: - 水平核线影像:alpha=0,生成水平对齐的核线 - 垂直核线影像:水平影像旋转90- 最接近原始:alpha=-1,最大化保留有效像素区域 ### 投影矩阵分析: 1. **第一幅图投影矩阵**: ``` -12179.875 7050.995 -2467.753 -1.732e+10 4723.739 5779.024 -11880.00 -2.204e+10 -0.4908 -0.5142 -0.7033 2.000e+06 ``` 2. **第二幅图投影矩阵**: ``` -12158.670 7092.358 -2453.755 -1.747e+10 4621.902 5524.719 -12039.97 -2.113e+10 -0.5028 -0.5235 -0.6878 2.038e+06 ``` 3. **相机位姿特点**: - 两相机位置相近但存在明显旋转差异(第三行方向向量不同) - 大数值平移表明相机距离场景较远(典型遥感特征) - 负值Z分量表明相机朝向地面(俯视角度)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值