2019年11月29日金曜日

ラズパイ(IOT・12)

前回購入したラズパイ4用のアルミケースを取り付けてみようと思います。
このケースのセットには、ケースのほかにねじとドライバー。そして、
冷却用のファンと、ファンを取り付けたねじ穴を隠すプレートと滑り止めも
ついていていい感じな内容になってます。
また、ファンを取り付けるためのケーブルをどこに刺すのかも、同梱してあるマニュアルに
絵付きで載っているので、初心者にも安心して取り付けることができます。

このファンを刺すピンは、ラズパイのGPIOポートに刺すのですが、
Interfacing Options のI2Cを有効にしなくても、普通に使えます。
あくまで制御するとき用ですね。

こんな感じになりました。
ロットによっては、ケースの蓋がはめにくいものがありましたが。
押し込めば大丈夫でした。
次回は、このケースを利用した温度の変化について検証してみます。



https://www.filetalk.info/index.html

2019年11月28日木曜日

ラズパイ(IOT・11)

ラズパイも3から4になり、HDMIの端子が2つになるなどの
関係でケースも互換性の無い新しいものへと変更
されています。
そこで、発熱量もおおいラズパイ4に合う、
ファン付きのアルミケースがあるので
取り付けてみようと思います。

見た目もかっこいいし、安っぽくないので
おすすめです。

ひとつ残念な点は、カメラ用のケーブル出す
すき間がないので、どうしても接続したい場合は、
横の蓋を付けない状態にする感じになります。(汗


https://www.filetalk.info/index.html

2019年11月27日水曜日

ラズパイ(IOT・10)

ラズパイ4のスペックアップは嬉しい限りですが、温度は?消費電力は?
そこで、まず温度を非接触で測れるこんなのが便利です。

先端を図りたい部分に向けてボタンを押すと、
温度が表示されます。

これを使って、チップの表面温度とかを計測して
いきたいと思います。
https://www.filetalk.info/index.html

2019年11月25日月曜日

ラズパイ(IOT・9)

待望のラズベリーパイの最新版である4が発売されて、
日本でも技適申請が通り、胸を張って使えるようになりました。
そこで、ラズパイ4を購入してみたので、色々確認してみようと思います。




まずは、スペック
Raspberry Pi 4 Model B
CPU:ARM Cortex-A72 1.5GHz
GPU:Broadcom VideoCore VI Dual Core 500MHz
メモリー:1GB, 2GB, 4GBの3種類


細かいことは、別のサイトに色々ありますので、
実際の使用感をお伝えしていこうと思います。
速度は、ラズパイ3から比べ、3倍高速とか言われていますが、
発熱を大きくなっていますので、
熱対策も必要かと思われます。

https://www.filetalk.info/index.html

2019年11月22日金曜日

ラズパイ(カメラ・29)

Three.jsを使った、RICOH R Development Kit の
360°動画ライブストリーミングぐりぐり操作の
ソースコードまとめ
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/>
<STYLE type="text/css">
* {
    margin: 0;
    padding: 0;
    border: 0;
}

body, html {
    overflow: hidden;
    height: 100%;
}

#stage {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

.bt {
 position: absolute;
 color: #ffffff;
}
.bt1 {
 left: 0px;
 top: 0px;
}
.bt2 {
 left: 40px;
 top: 0px;
}
.bt a {
 display: block;
 position: absolute;
 padding: 3px;
 color: #ffffff;
}
.bt a:hover {
 box-shadow: 0 0 45px rgba(255,255,255, 0.8);
}
</STYLE>
<script type="text/javascript" src="./js/three.min.js"></script>
<script type="text/javascript" src="./js/StereoEffect.js"></script>
<script type="text/javascript" src="./js/DeviceOrientationControls.js"></script>
<script type="text/javascript" src="./js/OrbitControls.js"></script>
<script type="text/javascript" src="./js/jquery.min.js"></script>
<script type="text/javascript" src="./js/hls.min.js"></script>
<SCRIPT>
var fov = 75;
var element;
var scene, camera, renderer, controls;
var sphere1;
var material1;
var texture1;
var onMouseDownMouseX = 0, onMouseDownMouseY = 0,
    lon = 0, onMouseDownLon = 0,
    lat = 0, onMouseDownLat = 0,
    phi = 0, theta = 0;
var isStereo = false;
var isFullScreen = false;
var video = document.createElement('video');

window.onload = function () {
  init();
};

function init() {
  if (Hls.isSupported()) {
    var hls = new Hls();
    hls.loadSource('./playlist.m3u8');
    hls.attachMedia(video);
    hls.on(Hls.Events.MANIFEST_PARSED, function() {
      video.play();
    });
  } else {
    console.log('his err');
  }
  
  var width = window.innerWidth;
  var height = window.innerHeight;
  scene = new THREE.Scene(); // シーンの作成
  // リサイズイベントを検知してリサイズ処理を実行
  window.addEventListener('resize', handleResize, false);
  // カメラの作成
  camera = new THREE.PerspectiveCamera(fov, width / height, 1, 1000);
  camera.position.set(0, 0, 0);
  scene.add(camera);
  // 球体の形状を作成
  var geometry = new THREE.SphereGeometry(5, 60, 40);
  geometry.scale(-1, 1, 1);
  // マテリアルの作成
  material1 = initMaterial('', 1);
  // 球体(形状)にマテリアル(質感)を貼り付けて物体を作成
  sphere1 = new THREE.Mesh(geometry, material1);
  // シーンに追加
  scene.add(sphere1);
  // レンダラーの作成
  renderer = new THREE.WebGLRenderer();
  // レンダラーをwindowサイズに合わせる
  renderer.setSize(width, height);
  renderer.setClearColor({color: 0x000000});
  effect = new THREE.StereoEffect(renderer);
  element = renderer.domElement;
  document.getElementById('stage').appendChild(element);
  renderer.render(scene, camera);
  // デバイスの判別
  var isAndroid = false;
  var isIOS = false;
  if (navigator.userAgent.indexOf('Android') != -1) {
    isAndroid = true; // デバイスがAndroidの場合
  } else if (/(iPad|iPhone|iPod)/g.test(navigator.userAgent)) {
  isIOS = true;  // デバイスがiOSの場合
  }
  if (isAndroid || isIOS) {
    // スマートフォンまたはタブレット端末の場合、ジャイロセンサーで視点操作を可能にする
    // ジャイロの取得には、SSLが必要(https://)
    window.addEventListener('deviceorientation', setOrientationControls, true);
  } else {
    setOrbitControls(); // パソコンの場合、マウスドラッグで視点操作を可能にする
  }
  
  render();
}

// リサイズ処理
function handleResize() {
  renderer.setSize(window.innerWidth, window.innerHeight);
  effect.setSize(window.innerWidth, window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
}

function getTexter(image) {
  return THREE.ImageUtils.loadTexture(image);
}

function initMaterial(image, opacity) {
  texture1 = new THREE.VideoTexture(video);
  texture1.minFilter = THREE.LinearFilter;
  material1 = new THREE.MeshBasicMaterial({ map: texture1 });
  return material1;
}


function onDocumentMouseDown(event) {
  event.preventDefault();
  if (event.clientX) {
    onMouseDownMouseX = event.clientX;
    onMouseDownMouseY = event.clientY;
  } else if (event.touches) {
    onMouseDownMouseX = event.touches[0].clientX
    onMouseDownMouseY = event.touches[0].clientY;
  } else {
    onMouseDownMouseX = event.changedTouches[0].clientX
    onMouseDownMouseY = event.changedTouches[0].clientY
  }
  onMouseDownLon = lon;
  onMouseDownLat = lat;
  if (window.ontouchstart === null) { //タッチ出来たら
    document.addEventListener('touchmove', onDocumentMouseMove, false);
    document.addEventListener('touchend', onDocumentMouseUp, false);
  } else {
    document.addEventListener('mousemove', onDocumentMouseMove, false);
    document.addEventListener('mouseup', onDocumentMouseUp, false);
  }
}

function onDocumentMouseMove( event ) {
  event.preventDefault();
  if (event.clientX) {
    var touchClientX = event.clientX;
    var touchClientY = event.clientY;
  } else if (event.touches) {
    var touchClientX = event.touches[0].clientX
    var touchClientY = event.touches[0].clientY;
  } else {
    var touchClientX = event.changedTouches[0].clientX
    var touchClientY = event.changedTouches[0].clientY
  }
  lon = (touchClientX - onMouseDownMouseX) * -0.1 + onMouseDownLon;
  lat = (touchClientY - onMouseDownMouseY) * -0.1 + onMouseDownLat;
}

function onDocumentMouseUp(event) {
  if (window.ontouchstart === null) { // タッチ出来たら
    document.removeEventListener('touchmove', onDocumentMouseMove, false);
    document.removeEventListener('touchend', onDocumentMouseUp, false);
  } else {
    document.removeEventListener('mousemove', onDocumentMouseMove, false);
    document.removeEventListener('mouseup', onDocumentMouseUp, false);
  }
}

// パソコン閲覧時マウスドラッグで視点操作する
function setOrbitControls() {
  controls = new THREE.OrbitControls(camera, element);
  controls.target.set(
    camera.position.x + 0.15,
    camera.position.y,
    camera.position.z
  );
  controls.enableDamping = true; // 視点操作のイージングをONにする
  controls.dampingFactor = 0.2;  // 視点操作のイージングの値
  controls.rotateSpeed = 0.1;  // 視点変更の速さ
  controls.noZoom = false;   // ズーム禁止
  controls.noPan = false;   // パン操作禁止
}

// ジャイロセンサーで視点操作する
function setOrientationControls(e) {
  if (!e.alpha) return; // スマートフォン以外で処理させない
  controls = new THREE.DeviceOrientationControls(camera, true);
  controls.connect();
  controls.update();
  window.removeEventListener("deviceorientation", setOrientationControls, true);
}

function render() {
  lat = Math.max(-90, Math.min(90, lat));
  phi = THREE.Math.degToRad(90 - lat);
  theta = THREE.Math.degToRad(lon);
  
  var angle = (theta * 360 / Math.PI);
  if (angle > 360) {
    var tmp = Math.floor(angle / 360);
    if (tmp > 0) angle = angle - (360 * tmp);
  } else if (angle < 0) {
    var tmp = Math.floor(angle / 360);
    if (tmp < 0) angle = angle + (360 * tmp * -1);
  }
  var deg = (theta * 360 / Math.PI) * -1;
  if (deg > 180) {
    var tmp = Math.floor(deg / 180);
    deg = (180 * tmp * -1) + deg - 180;
    if (tmp % 2 == 0) deg += 180;
  } else if (deg < -180) {
    var tmp = Math.floor(deg / 180) * -1;
    deg = deg + (180 * (tmp * -1) * -1);
    if (tmp % 2 > 0) deg -= 180;
  }
  
  $('#courseBox').css({
    transform: 'rotate(' + (deg * -1) + 'deg)'
  });
  $('#arrowBox').css({
    transform: 'rotate(' + (deg * -1) + 'deg)'
  });
  
  requestAnimationFrame(render);
  renderer.render(scene, camera);
  if (isStereo) {
    camera.fov = fov;
    effect.render(scene, camera);
  }
  
  controls.update();
}

function setStereoScreen() {
  isStereo = !isStereo;
  if (isStereo) {
    if (!isFullScreen) setFullScreen();
  } else
    setFullScreen();
}

function setFullScreen() {
  var fulltarget = document.getElementById('stage');
  if (!isFullScreen) {
    if (fulltarget.webkitRequestFullscreen) {
      fulltarget.webkitRequestFullscreen(); // Chrome15+, Safari5.1+, Opera15+
    } else if (fulltarget.mozRequestFullScreen) {
      fulltarget.mozRequestFullScreen(); // FF10+
    } else if (fulltarget.msRequestFullscreen) {
      fulltarget.msRequestFullscreen();  // IE11+
    } else if (fulltarget.requestFullscreen) {
      fulltarget.requestFullscreen();  // HTML5 Fullscreen API仕様
    } else {
      alert('ご利用のブラウザはフルスクリーン操作に対応していません');
      return;
    }
    $('#scrimg').attr('src', 'img/win.png');
    isFullScreen = true;
  } else {
    if (document.webkitCancelFullScreen) {
      document.webkitCancelFullScreen(); // Chrome15+, Safari5.1+, Opera15+
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen();  // FF10+
    } else if (document.msExitFullscreen) {
      document.msExitFullscreen();   // IE11+
    } else if (document.cancelFullScreen) {
      document.cancelFullScreen();   // Gecko:FullScreenAPI仕様
    } else if (document.exitFullscreen) {
      document.exitFullscreen();   // HTML5 Fullscreen API仕様
    }
    $('#scrimg').attr('src', 'img/full.png');
    isFullScreen = false;
    if (isStereo) isStereo = false;
  }
}
</SCRIPT>
</head>

<body>
  <div id="stage">
    <div class="bt bt1"><a href="#" onclick="setStereoScreen();"><img src="img/vr.png" /></a></div>
    <div class="bt bt2"><a href="#" onclick="setFullScreen();"><img id="scrimg" src="img/full.png" /></a></div>
  </div>
</body>
</html>


https://www.filetalk.info/index.html

2019年11月21日木曜日

ラズパイ(カメラ・28)

続きまして、両眼対応の表示ができるようにしてみます。
画面を2つにわけて、それぞれを別の角度から見れるように
することで、VR表示ができるようにしてみます。
同じく、Three.js に機能を追加します。
  <script type="text/javascript" src="./js/StereoEffect.js"></script>

var isStereo = false;

  if (isStereo) {
    camera.fov = fov;
    effect.render(scene, camera);
  }

function setStereoScreen() {
  isStereo = !isStereo;
  if (isStereo) {
    if (!isFullScreen) setFullScreen();
  } else
    setFullScreen();
}


あとは、プラグインのJavaScriptがいいように調整してくれます。


https://www.filetalk.info/index.html

2019年11月20日水曜日

ラズパイ(カメラ・27)

前回、Three.jsをつかってグリグリ動かせるWebページの
ベースができましたので、おつぎは、スマホで表示
したときに、傾けた角度によって視点が
変わるようにジャイロに対応してみます。
変更する部分は、以下となります。
<script type="text/javascript" src="./js/DeviceOrientationControls.js"></script>

  if (isAndroid || isIOS) {
    // スマートフォンまたはタブレット端末の場合、ジャイロセンサーで視点操作を可能にする
    // ジャイロの取得には、SSLが必要(https://)
    window.addEventListener('deviceorientation', setOrientationControls, true);
  } else {
    setOrbitControls(); // パソコンの場合、マウスドラッグで視点操作を可能にする
  }

// ジャイロセンサーで視点操作する
function setOrientationControls(e) {
  if (!e.alpha) return; // スマートフォン以外で処理させない
  controls = new THREE.DeviceOrientationControls(camera, true);
  controls.connect();
  controls.update();
  window.removeEventListener("deviceorientation", setOrientationControls, true);
}


ただ、最近のセキュリティ管理の一環で、以前はこれで動いていましたが、
SSLが設置されているサイトでないと角度を取ることができなくなってしまっている
ようです(汗

https://www.filetalk.info/index.html

2019年11月18日月曜日

ラズパイ(カメラ・26)

360°の映像をブラウザから視点操作は、3Dの球体オブジェクトに
動画画像を貼り付けて、操作するイメージになります。
基本は、インストールなしで誰にでも見てもらえるような
コンテンツにしたいのでJavaScriptで作成された
ライブラリを使うことになります。
有名どころには、手軽に組み込める A-Frame https://aframe.io/
と、A-Frame のベースになっている Three.js https://threejs.org/
があります。
今回は、カスタマイズが色々可能である Three.js をベースに
作っていきたいと思います。

まず、全体の画面用のページを作成します。
  

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/>
<STYLE type="text/css">
* {
    margin: 0;
    padding: 0;
    border: 0;
}

body, html {
    overflow: hidden;
    height: 100%;
}

#stage {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

.bt {
 position: absolute;
 color: #ffffff;
}
.bt1 {
 left: 0px;
 top: 0px;
}
.bt2 {
 left: 40px;
 top: 0px;
}
.bt a {
 display: block;
 position: absolute;
 padding: 3px;
 color: #ffffff;
}
.bt a:hover {
 box-shadow: 0 0 45px rgba(255,255,255, 0.8);
}
</STYLE>
<script type="text/javascript" src="./js/three.min.js"></script>
<script type="text/javascript" src="./js/OrbitControls.js"></script>
<script type="text/javascript" src="./js/jquery.min.js"></script>
<script type="text/javascript" src="./js/hls.min.js"></script>
<SCRIPT>
var fov = 75;
var element;
var scene, camera, renderer, controls;
var sphere1;
var material1;
var texture1;
var onMouseDownMouseX = 0, onMouseDownMouseY = 0,
    lon = 0, onMouseDownLon = 0,
    lat = 0, onMouseDownLat = 0,
    phi = 0, theta = 0;
var isFullScreen = false;
var video = document.createElement('video');

window.onload = function () {
  init();
};

function init() {
  if (Hls.isSupported()) {
    var hls = new Hls();
    hls.loadSource('./playlist.m3u8');
    hls.attachMedia(video);
    hls.on(Hls.Events.MANIFEST_PARSED, function() {
      video.play();
    });
  } else {
    console.log('his err');
  }
  
  var width = window.innerWidth;
  var height = window.innerHeight;
  scene = new THREE.Scene(); // シーンの作成
  // リサイズイベントを検知してリサイズ処理を実行
  window.addEventListener('resize', handleResize, false);
  // カメラの作成
  camera = new THREE.PerspectiveCamera(fov, width / height, 1, 1000);
  camera.position.set(0, 0, 0);
  scene.add(camera);
  // 球体の形状を作成
  var geometry = new THREE.SphereGeometry(5, 60, 40);
  geometry.scale(-1, 1, 1);
  // マテリアルの作成
  material1 = initMaterial('', 1);
  // 球体(形状)にマテリアル(質感)を貼り付けて物体を作成
  sphere1 = new THREE.Mesh(geometry, material1);
  // シーンに追加
  scene.add(sphere1);
  // レンダラーの作成
  renderer = new THREE.WebGLRenderer();
  // レンダラーをwindowサイズに合わせる
  renderer.setSize(width, height);
  renderer.setClearColor({color: 0x000000});
  effect = new THREE.StereoEffect(renderer);
  element = renderer.domElement;
  document.getElementById('stage').appendChild(element);
  renderer.render(scene, camera);
  setOrbitControls(); // パソコンの場合、マウスドラッグで視点操作を可能にする
      
  render();
}

// リサイズ処理
function handleResize() {
  renderer.setSize(window.innerWidth, window.innerHeight);
  effect.setSize(window.innerWidth, window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
}

function getTexter(image) {
  return THREE.ImageUtils.loadTexture(image);
}

function initMaterial(image, opacity) {
  texture1 = new THREE.VideoTexture(video);
  texture1.minFilter = THREE.LinearFilter;
  material1 = new THREE.MeshBasicMaterial({ map: texture1 });
  return material1;
}


function onDocumentMouseDown(event) {
  event.preventDefault();
  if (event.clientX) {
    onMouseDownMouseX = event.clientX;
    onMouseDownMouseY = event.clientY;
  } else if (event.touches) {
    onMouseDownMouseX = event.touches[0].clientX
    onMouseDownMouseY = event.touches[0].clientY;
  } else {
    onMouseDownMouseX = event.changedTouches[0].clientX
    onMouseDownMouseY = event.changedTouches[0].clientY
  }
  onMouseDownLon = lon;
  onMouseDownLat = lat;
  if (window.ontouchstart === null) { //タッチ出来たら
    document.addEventListener('touchmove', onDocumentMouseMove, false);
    document.addEventListener('touchend', onDocumentMouseUp, false);
  } else {
    document.addEventListener('mousemove', onDocumentMouseMove, false);
    document.addEventListener('mouseup', onDocumentMouseUp, false);
  }
}

function onDocumentMouseMove( event ) {
  event.preventDefault();
  if (event.clientX) {
    var touchClientX = event.clientX;
    var touchClientY = event.clientY;
  } else if (event.touches) {
    var touchClientX = event.touches[0].clientX
    var touchClientY = event.touches[0].clientY;
  } else {
    var touchClientX = event.changedTouches[0].clientX
    var touchClientY = event.changedTouches[0].clientY
  }
  lon = (touchClientX - onMouseDownMouseX) * -0.1 + onMouseDownLon;
  lat = (touchClientY - onMouseDownMouseY) * -0.1 + onMouseDownLat;
}

function onDocumentMouseUp(event) {
  if (window.ontouchstart === null) { // タッチ出来たら
    document.removeEventListener('touchmove', onDocumentMouseMove, false);
    document.removeEventListener('touchend', onDocumentMouseUp, false);
  } else {
    document.removeEventListener('mousemove', onDocumentMouseMove, false);
    document.removeEventListener('mouseup', onDocumentMouseUp, false);
  }
}

// パソコン閲覧時マウスドラッグで視点操作する
function setOrbitControls() {
  controls = new THREE.OrbitControls(camera, element);
  controls.target.set(
    camera.position.x + 0.15,
    camera.position.y,
    camera.position.z
  );
  controls.enableDamping = true; // 視点操作のイージングをONにする
  controls.dampingFactor = 0.2;  // 視点操作のイージングの値
  controls.rotateSpeed = 0.1;  // 視点変更の速さ
  controls.noZoom = false;   // ズーム禁止
  controls.noPan = false;   // パン操作禁止
}

function render() {
  lat = Math.max(-90, Math.min(90, lat));
  phi = THREE.Math.degToRad(90 - lat);
  theta = THREE.Math.degToRad(lon);
  
  var angle = (theta * 360 / Math.PI);
  if (angle > 360) {
    var tmp = Math.floor(angle / 360);
    if (tmp > 0) angle = angle - (360 * tmp);
  } else if (angle < 0) {
    var tmp = Math.floor(angle / 360);
    if (tmp < 0) angle = angle + (360 * tmp * -1);
  }
  var deg = (theta * 360 / Math.PI) * -1;
  if (deg > 180) {
    var tmp = Math.floor(deg / 180);
    deg = (180 * tmp * -1) + deg - 180;
    if (tmp % 2 == 0) deg += 180;
  } else if (deg < -180) {
    var tmp = Math.floor(deg / 180) * -1;
    deg = deg + (180 * (tmp * -1) * -1);
    if (tmp % 2 > 0) deg -= 180;
  }
  
  $('#courseBox').css({
    transform: 'rotate(' + (deg * -1) + 'deg)'
  });
  $('#arrowBox').css({
    transform: 'rotate(' + (deg * -1) + 'deg)'
  });
  
  requestAnimationFrame(render);
  renderer.render(scene, camera);
  
  controls.update();
}

function setFullScreen() {
  //var fulltarget = document.getElementsByClassName('fullsc')[0];
  var fulltarget = document.getElementById('stage');
  if (!isFullScreen) {
    if (fulltarget.webkitRequestFullscreen) {
      fulltarget.webkitRequestFullscreen(); // Chrome15+, Safari5.1+, Opera15+
    } else if (fulltarget.mozRequestFullScreen) {
      fulltarget.mozRequestFullScreen(); // FF10+
    } else if (fulltarget.msRequestFullscreen) {
      fulltarget.msRequestFullscreen();  // IE11+
    } else if (fulltarget.requestFullscreen) {
      fulltarget.requestFullscreen();  // HTML5 Fullscreen API仕様
    } else {
      alert('ご利用のブラウザはフルスクリーン操作に対応していません');
      return;
    }
    $('#scrimg').attr('src', 'img/win.png');
    isFullScreen = true;
  } else {
    if (document.webkitCancelFullScreen) {
      document.webkitCancelFullScreen(); // Chrome15+, Safari5.1+, Opera15+
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen();  // FF10+
    } else if (document.msExitFullscreen) {
      document.msExitFullscreen();   // IE11+
    } else if (document.cancelFullScreen) {
      document.cancelFullScreen();   // Gecko:FullScreenAPI仕様
    } else if (document.exitFullscreen) {
      document.exitFullscreen();   // HTML5 Fullscreen API仕様
    }
    $('#scrimg').attr('src', 'img/full.png');
    isFullScreen = false;
  }
}
</SCRIPT>
</head>

<body>
  <div id="stage">
    <div class="bt bt2"><a href="#" onclick="setFullScreen();"><img id="scrimg" src="img/full.png" /></a></div>
  </div>
</body>
</html>



https://www.filetalk.info/index.html

2019年11月15日金曜日

ラズパイ(カメラ・25)

前回つづいて、RICOH R Development Kitをつかって
360°のライブ配信をラズパイからできるように、
Webサーバー用のプログラムを調整します。
import os
import http.server
import socketserver

PORT = 8000

#--------------------------------------------------------------------------
# 開始
#--------------------------------------------------------------------------
def run():
    web_dir = os.path.join(os.path.dirname(__file__), '/home/pi/Public')
    os.chdir(web_dir)
    
    Handler = http.server.SimpleHTTPRequestHandler
    httpd = socketserver.TCPServer(("", PORT), Handler)
    print("serving at port", PORT)
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
    
    httpd.server_close()

if (__name__ == "__main__"):
    run()

これで配信する映像をホームページから
見えるように準備されました。次回は、
360°の映像をブラウザから視点操作が
できるようにページを作成します。

https://www.filetalk.info/index.html

2019年11月14日木曜日

ラズパイ(カメラ・24)

 さてさて、リコーの360°カメラが届いたので、
さっそく接続してビデオ動画を取得してみようと思います。

まず、ラズパイにUSBで接続し、どのポートに
接続されたのかを確認します。
$ v4l2-ctl --list-device



上記のコマンドからデバイス番号を確認し、
動画配信用のコマンドとして
前回使ったHLSのコードを変更します。
httpDir=~/Public
cd $httpDir

ffmpeg -f alsa -thread_queue_size 2048 \
  -i plughw:1,0 \
  -f v4l2 -thread_queue_size 1024 -input_format yuyv422 -video_size 1920x1080 \
  -i /dev/video1 \
  -filter_complex scale=1920x1080,fps=30 \
  -c:v h264_omx -b:v 2438k -g 24 \
  -c:a aac -b:a 64k \
  -flags +cgop+global_header \
  -f hls \
  -hls_time 4 -hls_list_size 3 -hls_allow_cache 0 \
  -hls_segment_filename $httpDir/stream/stream_%d.ts \
  -hls_base_url stream/ \
  -hls_flags delete_segments \
  $httpDir/playlist.m3u8

rm $httpDir/stream/stream_*.ts
rm $httpDir/playlist.m3u8


RICOH R Development Kitでは、解像度がフルHDなので
解像度などを調整します。

https://www.filetalk.info/index.html

2019年11月1日金曜日

ラズパイ(カメラ・23)

カメラにも色々種類がありますが、
近年のウェアラブルカメラをはじめインスタ360や
リコーのシータなどの360°カメラも手軽に買えるほどに
普及しています。
今回は、VR用にも使える360°カメラのTHETAシリーズの中で
唯一ストリーミング配信が24時間使用にも耐えうると
宣伝の RICOH R Development Kit を試してみます。

https://ricohr.ricoh/ja/
RICOH R Development Kit の特徴としましては、
・FullHD画質で、電源を付けたら即ストリーミングモード
・バッテリー搭載なしで、リチウムの寿命に気を付けなくてOK
・連続稼働OK
・リアルタイムスティッチングで画像の加工必要なし
という感じで、値段が通常のシータと比べて
お高めなことを除けば、他の機器から制御するために
利用するには最高に便利な一品です。


次回は、まず接続を試してみます。
https://www.filetalk.info/index.html