ros中相機話題在web頁面上的顯示,嘗試js解析sensor_msgs/Image數據

ros中相機話題在web頁面上的顯示

思路:
rosbridge websocket 開啟ros與web的通路,
話題數據轉換為image或者繪制在 canvas中。

話題格式:
sensor_msgs/Image
測試數據編碼類型為bgr8

嘗試:

解析 為bitmap arraybuffer 寫入bgr8,顏色錯誤
轉換顏色通道arraybuffer 填到 canvas
直接繪制為canvas
直接 顯示image

占用資源很高,顯示不太流暢,待優化

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" /><script src="js/three.min.js"></script>
<script src="js/eventemitter2.js"></script>
<script src="js/roslib.js"></script>
<script src="js/ros3d.js"></script><!--
<script src="https://cdn.jsdelivr.net/npm/three@0.89.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/eventemitter2@6.4/lib/eventemitter2.js"></script>
<script src="https://cdn.jsdelivr.net/npm/roslib@1/build/roslib.js"></script>
<script src="../build/ros3d.js"></script>
-->
<script>/*** Setup all visualization elements when the page is loaded.*/function init() {// Connect to ROS.var ros = new ROSLIB.Ros({//url : 'ws://192.168.20.104:9090'url : 'ws://192.168.10.168:9090'});ros.on('connection', function() {console.log('Connected to websocket server.');});ros.on('error', function(error) {console.log('Error connecting to websocket server: ', error);});ros.on('close', function() {console.log('Connection to websocket server closed.');});var canvas = document.getElementById('img_canvas');canvas.width = 800;canvas.height = 600;var image = new Image();document.body.appendChild(image);image.onload = function() {var canvasWidth=canvas.width ;var canvasHeight=canvas.height;var imageWidth = image.width;var imageHeight = image.height;var imageAspectRatio = imageWidth / imageHeight;var canvasAspectRatio = canvasWidth / canvasHeight;var scaledWidth=1.0;var scaledHeight=1.0;if (imageAspectRatio > canvasAspectRatio) {scaledWidth = canvasWidth;scaledHeight = Math.round(scaledWidth / imageAspectRatio);} else {scaledHeight = canvasHeight;scaledWidth = Math.round(scaledHeight * imageAspectRatio);}var x = (canvasWidth - scaledWidth) / 2;var y = (canvasHeight - scaledHeight) / 2;ctx = canvas.getContext('2d');// 設置背景色并填充整個畫布ctx.fillStyle = "#f0f0f0"; // 淺灰色ctx.fillRect(0, 0, canvasWidth, canvasHeight);ctx.drawImage(image, x, y, scaledWidth, scaledHeight);};var example2 = ros.Topic({name: '/usb_cam/image_raw',messageType: 'sensor_msgs/Image'});var ccc=0function generateBMP(width,height,channel) {//var channel=3;//const width = 100;//const height = 100;const fileSize = 54 + width * height * channel; // Header size + pixel data sizevar  buffer = new ArrayBuffer(fileSize);const data = new DataView(buffer);// BMP Headerdata.setUint8(0, 0x42); // 'B'data.setUint8(1, 0x4d); // 'M'data.setUint32(2, fileSize, true); // file sizedata.setUint32(6, 0, true); // reserveddata.setUint32(10, 54, true); // pixel data offset// DIB Headerdata.setUint32(14, 40, true); // DIB header sizedata.setUint32(18, width, true); // widthdata.setUint32(22, height, true); // heightdata.setUint16(26, 1, true); // planesdata.setUint16(28, channel*8, true); // bits per pixel (32-bit)data.setUint32(30, 0, true); // compression (none)//data.setUint32(34, width * height * 4, true); // image sizedata.setUint32(34, width * height * channel, true); // image size --------------zzzdata.setUint32(38, 2835, true); // horizontal resolution (72 DPI)data.setUint32(42, 2835, true); // vertical resolution (72 DPI)data.setUint32(46, 0, true); // colors in palette (none)data.setUint32(50, 0, true); // important colors (all)// Pixel data (simple gradient with transparency)let offset = 54;for (let y = 0; y < height; y++) {for (let x = 0; x < width; x++) {const red = (x / width) * 255;const green = (y / height) * 255;const blue = ((x + y) / (width + height)) * 255;const alpha = (x / width) * 255; // Varying alpha//for transparencydata.setUint8(offset++, blue); // bluedata.setUint8(offset++, green); // greendata.setUint8(offset++, red); // red//data.setUint8(offset++, alpha); // alpha}}const blob = new Blob([buf], { type: "image/bmp" });image.src = URL.createObjectURL(blob);return buffer}var buf=null;example2.subscribe(function(message) {ccc++;if (ccc==1){buf=generateBMP(message.width, message.height,3)}//console.log('Received image seq=%d', message['header']['seq']);//AI???//const image = new ROSLIB.Image(); // 創建 Image 對象實例//image.data = new Uint8Array(message.data); // 設置圖像數據//image.width = message.width; // 設置圖像寬度//image.height = message.height; // 設置圖像高度//image.encoding = message.encoding; // 設置圖像編碼格式,例如 'rgb8' 或 'mono8' 等//if (ccc%5!=1){return;}let raw = window.atob(message.data);let rawLength = raw.length;//buf.set(raw, 54);a=rawLength/3b=new Uint8Array(buf)
/*b.set(raw.split('').map(char => char.charCodeAt(0)), 54);const blob = new Blob([b.buffer], { type: "image/bmp" });image.src = URL.createObjectURL(blob);//*//*// 將base64字符串中的每個字符轉換成ASCII碼(字符編碼值)for (let i = 0; i < a; i++) {b[54+i*3] = raw.charCodeAt(i*3+2);b[54+i*3+2] = raw.charCodeAt(i*3);b[54+i*3+1] = raw.charCodeAt(i*3+1);}const blob = new Blob([b.buffer], { type: "image/bmp" });image.src = URL.createObjectURL(blob);//*///*var ctx = canvas.getContext('2d');var imageData = ctx.createImageData(message.width, message.height); // 創建ImageData對象//console.log('Received image', message.width, message.height,message.step, message.encoding);// 創建一個Uint8Array類型的數組let uInt8Array = new Uint8Array(rawLength/3*4);// 將base64字符串中的每個字符轉換成ASCII碼(字符編碼值)for (let i = 0; i < a; i++) {uInt8Array[i*4] = raw.charCodeAt(i*3);uInt8Array[i*4+1] = raw.charCodeAt(i*3+1);uInt8Array[i*4+2] = raw.charCodeAt(i*3+2);uInt8Array[i*4+3] = 255;}imageData.data.set(uInt8Array); // 將圖像數據轉換為Uint8ClampedArray并設置到ImageData對象中ctx.putImageData(imageData, 0, 0); // 將ImageData繪制到Canvas上
//*//*//console.log('Received image', message.width, message.height,message.step, message.encoding);var ctx = canvas.getContext('2d');var imageData = ctx.createImageData(message.width, message.height); // 創建ImageData對象// 將base64字符串中的每個字符轉換成ASCII碼(字符編碼值)for (let i = 0; i < a; i++) {imageData.data[i*4] = raw.charCodeAt(i*3);imageData.data[i*4+1] = raw.charCodeAt(i*3+1);imageData.data[i*4+2] = raw.charCodeAt(i*3+2);imageData.data[i*4+3] = 255;   }ctx.putImageData(imageData, 0, 0); // 將ImageData繪制到Canvas上
//*/});}
</script>
</head><body onload="init()"><h1>sensor_msgs/Image Example</h1>
<!--<p>Run the following commands in the terminal then refresh the page.</p><ol><li><tt>roscore</tt></li><li><tt>roslaunch rosbridge_server rosbridge_websocket.launch</tt></li><li><tt>rosrun tf2_web_republisher tf2_web_republisher</tt></li><li><tt>roslaunch openni_launch openni.launch depth_registration:=true</tt></li></ol>
--><canvas id="img_canvas"> </canvas>
</body>
</html>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84378.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84378.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84378.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PowerShell批量處理文件名稱/內容的修改

在日常的文件管理與處理中&#xff0c;常常需要對大量文件名或文件內容進行修改&#xff0c;而手動逐個操作既繁瑣又容易出錯。PowerShell作為一種強大的腳本語言&#xff0c;為我們提供了高效批量處理文件名及內容修改的解決方案。通過編寫簡單的PowerShell腳本&#xff0c;可…

GA3C(GPU/CPU混合式異步優勢Actor-Critic)算法實現控制倒立擺

GA3C算法實現倒立擺 完整代碼在文章結尾 GA3C算法 GPU/CPU混合式異步優勢AC算法&#xff0c;是由A3C算法進一步優化而來&#xff0c;為了更好利用GPU計算資源。 GA3C理論上與A3C相同&#xff0c;屬于On-Policy。但由于存在延遲更新問題&#xff0c;導致用于策略更新的數據并…

基礎RAG實現,最佳入門選擇(六)

帶有問題生成的文檔增強RAG 通過問題生成使用文檔增強來實現增強的RAG方法。通過為每個文本塊生成相關問題&#xff0c;改進了檢索過程&#xff0c;從而從語言模型中獲得更好的響應。 具體實現步驟 1.數據攝取&#xff1a;從PDF文件中提取文本。 2.chunking&#xff1a;將文本…

vue3 電商類網站實現規格的選擇

目前有一個這樣的需求 類似淘寶 京東選擇 但是在人家大廠給的數據我不清除是什么樣子的 我這邊后端給的數據 一開始是想把規格全部顯示出來的 發現實現不了 后端的數據有限 因為必須選擇一個顏色 才可以對應的第二個規格 才知道有沒有庫存 因為這個庫存 是由兩個規格決定…

HarmonyOS5 音樂播放器app(一):歌曲展示與收藏功能(附代碼)

鴻蒙音樂應用開發&#xff1a;從收藏功能實現看狀態管理與交互設計 在移動應用開發中&#xff0c;收藏功能是用戶體驗的重要組成部分。本文將以鴻蒙OS音樂應用為例&#xff0c;詳細解析如何實現具有動畫效果的收藏功能&#xff0c;涉及狀態管理、組件通信和交互動畫等核心技術…

PHP函數大全參考代碼

字符串相關操作函數 去除空格或其他字符 trim刪除字符串兩端空格或其他預定義字符rtrim刪除字符串右邊空格或其他預定義字符choprtrim() 的別名 chop() 與 Perl 的 chop() 函數有所不同&#xff0c;它會刪除字符串的最后一個字符。ltrim刪除字符串左邊空格或其他預定義字符 字…

Flowise工作流引擎的本地部署與遠程訪問實踐

文章目錄 前言1. Docker安裝Flowise2. Ubuntu安裝Cpolar3. 配置Flowise公網地址4. 遠程訪問Flowise5. 固定Cpolar公網地址6. 固定地址訪問 前言 當多數團隊仍深陷傳統數據處理框架的桎梏時&#xff0c;創新者已率先引入Flowise智能流程引擎&#xff0c;成功將面向大型語言模型…

端側AI+OS垂直創新研究報告

端側AIOS垂直創新研究報告 摘要 端側AIOS研究背景、核心創新點及產業價值 研究背景 隨著AI技術的快速發展&#xff0c;端側AI已成為2025年的重要技術趨勢[4]。端側AI是指將AI計算能力從云端遷移到終端設備上&#xff0c;實現本地化的智能處理。這一技術變革主要受到隱私安全…

【JVM 07-運行時常量池重要組成部分-StringTable】

StringTable 筆記記錄 1. 常量池、運行時常量池與字符串常量池(StringTable)的關系2. String str"a"放入字符串常量池的過程3. 常見面試題4. StringTable特性5.StringTable的位置變更5.1 為什么位置變換&#xff1f;5.2 位置變更演示 6. StringTable垃圾回收7. Strin…

算法-每日一題(DAY10)打家劫舍

1.題目鏈接&#xff1a; 198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 2.題目描述&#xff1a; 你是一個專業的小偷&#xff0c;計劃偷竊沿街的房屋。每間房內都藏有一定的現金&#xff0c;影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統&#xf…

android UI 布局

一&#xff1a;約束布局 參考&#xff1a; 【約束布局】ConstraintLayout 約束布局 ( 簡介 | 引入依賴 | 基本操作 | 垂直定位約束 | 角度定位約束 | 基線約束 )_韓曙亮-2048 AI社區 以下是一個基于 ConstraintLayout 的簡單 Android 示例&#xff0c;包含三個控件&#xff0…

【K8S】詳解Labels?? 和 ??Annotations

在 Kubernetes&#xff08;K8s&#xff09;中&#xff0c;??Labels&#xff08;標簽&#xff09;?? 和 ??Annotations&#xff08;注解&#xff09;?? 都是用于為資源對象&#xff08;如 Pod、Service、Deployment&#xff09;附加元數據的機制&#xff0c;但它們在設計…

系統模塊編程與實現

設備類&#xff08;Device Class&#xff09;?? 和 ??設備節點&#xff08;Device Node&#xff09;??是深入 Linux 設備管理和驅動模型的核心基礎。它們就像“骨骼”與“門戶”&#xff0c;共同構建了 Linux 與硬件交互的核心橋梁。 一、設備類與設備節點 1. ??設備…

視頻壓縮、碼率與流媒體傳輸知識總結

&#x1f3a5; 視頻壓縮、碼率與流媒體傳輸知識總結 本筆記整理了 I/P/B 幀結構、碼率計算、文件大小估算、壓縮格式對比、推流帶寬建議等視頻工程常見技術要點。 一、單幀與未壓縮視頻數據量估算 分辨率&#xff1a;19201080&#xff08;1080p&#xff09; 色深&#xff1a;…

嵌入式C++學習路線

&#x1f680; 嵌入式C學習路線圖 從C語言基礎到嵌入式C高手的完整路徑 &#x1f4cb; 學習進度追蹤 總體目標&#xff1a; 20-26周完成全部學習內容 前置條件&#xff1a; C語言基礎 STM32開發經驗 學習方式&#xff1a; 理論學習 實踐項目 階段1: C基礎過渡 (2-3周) 目標…

VSCode1.101.1Win多語言語言編輯器便攜版安裝教程

軟件下載 【名稱】&#xff1a; VSCode1.101.1 【大小】&#xff1a; 120M 【語言】&#xff1a; 簡體中文 【安裝環境】&#xff1a; Win10/Win11 【迅雷網盤下載鏈接】&#xff08;務必手機注冊&#xff09;&#xff1a; 迅雷 【網站下載鏈接】: 其他網盤 軟件介紹 VSCod…

ssh 服務和 rsync 數據同步

目錄 一、ssh服務 1、概述 2、命令解析 遠程登錄命令 遠程拷貝命令 3、登錄方式配置 1、用戶名密碼登錄 2、公鑰驗證登錄 二、rsync 數據同步 1、rsync概述 2、rsync運行原理 3、rsync部署 一、ssh服務 1、概述 ssh服務&#xff0c;一種遠程管理連接工具&#xf…

使用隨機森林實現目標檢測

核心實現思路 滑動窗口策略&#xff1a;在圖像上滑動固定大小的窗口&#xff0c;對每個窗口進行分類多維特征提取&#xff1a;結合統計特征、紋理特征、邊緣特征、形狀特征等隨機森林分類&#xff1a;訓練二分類器判斷窗口是否包含目標后處理優化&#xff1a;使用非極大值抑制…

3.6 move_base導航初體驗

1.環境搭建 在工作空間src下git wpr_simulation&#xff0c;安裝install_for_noetic.sh&#xff0c;然后再回退工作空間進行編譯 下載參數文件 git clone https://github.com/6-robot/wpb_home.git下載需要魔法&#xff0c;在這里可以使用手機熱點進行平替 進入腳本文件夾 …

Mysql高級——MVCC(多版本并發控制)

MySQL MVCC&#xff08;多版本并發控制&#xff09;詳解 MVCC&#xff08;Multi-Version Concurrency Control&#xff09;是 MySQL InnoDB 存儲引擎實現的一種并發控制機制&#xff0c;用于在保證事務隔離性的同時&#xff0c;提高數據庫的并發性能。下面從原理、實現、事務隔…