[PYTHON] API RICOH THETA S en plusieurs langues.

At first

RICOH THETA API V2 Il existe une page de développement (https://developers.theta360.com/en/), une référence (https://developers.theta360.com/en/docs/v2/api_reference/) et un forum ](Https://developers.theta360.com/ja/forums/) est ouvert au public.

Cette page montre un exemple d'utilisation de l'API suivante basée sur Getting Started.

  1. Obtenez des informations sur le boîtier de l'appareil photo GET / osc / info
  2. Démarrer la session POST / osc / commands / execute camera.startSession
  3. Prise de vue d'images fixes POST / osc / commands / execute camera.takePicture
  4. Obtenir l'état de la prise de vue POST / OSC / state
  5. Get File POST / osc / commands / execute camera.getImage
  6. Fin de session POST / osc / commands / execute camera.closeSession

Fondamentalement, POST est utilisé pour échanger des paramètres et des réponses au format JSON.

Prerequisite

Shell Script Tout d'abord, afin d'obtenir une image du flux de traitement, frappons depuis Shell tout en vérifiant la réponse. Cette fois, nous utiliserons la commande "curl" qui est installée par défaut sur Mac OS X.

#Obtenir des informations sur le boîtier de l'appareil photo
$ curl http://192.168.1.1:80/osc/info
{"manufacturer":"RICOH","model":"RICOH THETA S","serialNumber":"XXXXXXXX","firmwareVersion":"01.11","supportUrl":"https://theta360.com/en/support/","endpoints":{"httpPort":80,"httpUpdatesPort":80},"gps":false,"gyro":false,"uptime":583,"api":["/osc/info","/osc/state","/osc/checkForUpdates","/osc/commands/execute","/osc/commands/status"]}

Les informations sur le boîtier de l'appareil photo ont été acquises. Cette valeur ne sera plus utilisée par la suite.

#Démarrer la session
$ curl -X POST http://192.168.1.1:80/osc/commands/execute -d '{"name": "camera.startSession"}'
{"name":"camera.startSession","state":"done","results":{ "sessionId":"SID_0001","timeout":180}}

Le "sessionId" obtenu ici sera utilisé plus tard. Vous devez le mettre manuellement à l'emplacement correspondant à "SID_0001" sur la ligne suivante.

#Prise d'images fixes
$ curl -X POST http://192.168.1.1:80/osc/commands/execute -d '{"name": "camera.takePicture", "parameters": {"sessionId": "SID_0001"}}'
{"name":"camera.takePicture","state":"inProgress","id":"2","progress":{"completion":0.0}}

La caméra s'appelle Cuin. La prise de vue de l'image prendra un certain temps.

#Acquisition du statut de prise de vue
$ curl -X POST http://192.168.1.1:80/osc/state
{"fingerprint":"FIG_0006","state":{"sessionId":"SID_0001","batteryLevel":1.0,"storageChanged":false,"_captureStatus":"idle","_recordedTime":0,"_recordableTime":0,"_latestFileUri":"100RICOH/R0010174.JPG","_batteryState":"charging"}}

Ici, utilisez "_latestFileUri" qui peut être obtenu lorsque le processus de prise de vue est terminé avec l'API suivante. S'il y a un changement dans "l'empreinte digitale", le traitement d'image est terminé. Vous devrez peut-être l'exécuter plusieurs fois jusqu'à ce que vous obteniez le "_latestFileUri".

#Acquisition de fichiers
$ curl -X POST http://192.168.1.1:80/osc/commands/execute -d '{"name": "camera.getImage", "parameters": {"fileUri": "100RICOH/R0010174.JPG"}}' > image.jpg && open image.jpg

Le fichier est pris et enregistré dans image.jpg dans le répertoire d'exécution. Il est ouvert dans la visionneuse après le ramassage.

#Fin de session
$ curl -X POST http://192.168.1.1:80/osc/commands/execute -d '{"name": "camera.closeSession", "parameters": {"sessionId": "SID_0001"}}'
{"name":"camera.closeSession","state":"done"}

Le nettoyage est terminé.

Il faut un certain temps pour spécifier les paramètres, mais je pense qu'il a été confirmé que vous pouvez facilement prendre et récupérer des images avec HTTP.

Ruby

require 'net/http'
require 'json'

http = Net::HTTP.new('192.168.1.1', 80)
JSON.parse(http.get("/osc/info").body)

res = http.post('/osc/commands/execute', {name: "camera.startSession"}.to_json)
sessionId = JSON.parse(res.body)["results"]["sessionId"]

params = {name: "camera.takePicture", parameters: {sessionId: sessionId}}.to_json
http.post('/osc/commands/execute', params)

fileUri = JSON.parse(http.post('/osc/state',"").body)["state"]["_latestFileUri"] while fileUri.empty?

params = {name: "camera.getImage", parameters: {fileUri: fileUri}}.to_json
res = http.post('/osc/commands/execute', params)

open("image.jpg ", "wb") {|f| f.write(res.body)}
`open image.jpg`

params = {name: "camera.closeSession", parameters: {sessionId: sessionId}}.to_json
http.post('/osc/commands/execute', params)

Je pense qu'il peut être lu intuitivement. J'aime Ruby.

Python

import urllib
import json

urllib.urlopen("http://192.168.1.1/osc/info").read()

data = json.dumps({"name":"camera.startSession"})
res = urllib.urlopen('http://192.168.1.1/osc/commands/execute', data)
sessionId = json.loads(res.read())["results"]["sessionId"]

data = json.dumps({"name":"camera.takePicture", "parameters": {"sessionId": sessionId}})
urllib.urlopen('http://192.168.1.1/osc/commands/execute', data)

fileUri = ""
while not fileUri:
    res = urllib.urlopen('http://192.168.1.1/osc/state', urllib.urlencode({}))
    fileUri = json.loads(res.read())["state"]["_latestFileUri"]

data = json.dumps({"name":"camera.getImage", "parameters": {"fileUri": fileUri}})
res = urllib.urlopen('http://192.168.1.1/osc/commands/execute', data)
with open("image.jpg ", "wb") as file:
    file.write(res.read())

data = json.dumps({"name":"camera.closeSession", "parameters": {"sessionId": sessionId}})
urllib.urlopen('http://192.168.1.1/osc/commands/execute', data)

Je pense que vous pouvez également lire cela intuitivement.

Je voulais ouvrir l'image, mais lorsque j'ai collé le code suivant ensemble après le code ci-dessus, le comportement de Popen n'était pas stable. Si elle est exécutée à tout moment, l'image peut être ouverte avec le code suivant même à partir de l'environnement REPL.

import subprocess
subprocess.Popen(['open', 'image.jpg'])

Swift

import UIKit

// for asynchronous use in Playground
import XCPlayground 
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true 

let session = NSURLSession.sharedSession()

// osc/info
var url = NSURL(string: "http://192.168.1.1/osc/info")
var task = session.dataTaskWithURL(url!) {
    (data, response, error) in
    print(NSString(data: data!, encoding: NSUTF8StringEncoding))
}
task.resume()

// camera.startSession
var sessionId = "";
var jsonDic = NSDictionary()
url = NSURL(string: "http://192.168.1.1/osc/commands/execute")
var req = NSMutableURLRequest(URL: url!)
var params: [String: AnyObject] = ["name": "camera.startSession"]
req.HTTPMethod = "POST"
req.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.PrettyPrinted)
task = session.dataTaskWithRequest(req) {
    (data, response, error) in
    print(NSString(data: data!, encoding: NSUTF8StringEncoding))
    do {
        jsonDic = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
    } catch {}
    let result = jsonDic["results"]  as! NSDictionary
    sessionId = result["sessionId"] as! String
}
task.resume()
while sessionId.isEmpty { sleep(1) }

// camera.takePicture
url = NSURL(string: "http://192.168.1.1/osc/commands/execute")
req = NSMutableURLRequest(URL: url!)
params = ["name": "camera.takePicture", "parameters": ["sessionId": sessionId]]
req.HTTPMethod = "POST"
req.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params,
    options: NSJSONWritingOptions.PrettyPrinted)
task = session.dataTaskWithRequest(req) {
    (data, response, error) in
    print(NSString(data: data!, encoding: NSUTF8StringEncoding))
}
task.resume()

// osc/state
var fileUri = "";
url = NSURL(string: "http://192.168.1.1/osc/state")
req = NSMutableURLRequest(URL: url!)
req.HTTPMethod = "POST"
repeat {
    sleep(1)
    print("try osc/state")
    task = session.dataTaskWithRequest(req) {
        (data, response, error) in
        print(NSString(data: data!, encoding: NSUTF8StringEncoding))
        do {
            jsonDic = try NSJSONSerialization.JSONObjectWithData(data!,
                options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
        } catch {}
        let result = jsonDic["state"]  as! NSDictionary
        fileUri = result["_latestFileUri"] as! String
    }
    task.resume()
} while fileUri.isEmpty
print(fileUri)

// camera.getImage
var img :UIImage?
url = NSURL(string: "http://192.168.1.1/osc/commands/execute")
req = NSMutableURLRequest(URL: url!)
params = ["name": "camera.getImage", "parameters": ["fileUri": fileUri]]
req.HTTPMethod = "POST"
req.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params,
    options: NSJSONWritingOptions.PrettyPrinted)
task = session.dataTaskWithRequest(req) {
    (data, response, error) in
//    NSData.init(data: data!)
    img = UIImage(data: data!)
}
task.resume()
while (img == nil) { sleep(1) }

// camera.closeSession
url = NSURL(string: "http://192.168.1.1/osc/commands/execute")
req = NSMutableURLRequest(URL: url!)
params = ["name": "camera.closeSession", "parameters": ["sessionId": sessionId]]
req.HTTPMethod = "POST"
req.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params,
    options: NSJSONWritingOptions.PrettyPrinted)
task = session.dataTaskWithRequest(req) {
    (data, response, error) in
    print(NSString(data: data!, encoding: NSUTF8StringEncoding))
}
task.resume()

Puisque NSURLSession est une API qui s'exécute de manière asynchrone, le traitement en attente est inséré ici et là. Lorsque la valeur est entrée dans img, vous pouvez vérifier l'image en prévisualisant la variable dans la barre latérale Résultats de l'environnement Playground. Je veux écrire un peu plus joliment lors du traitement de JSON.

Unity

C#

using UnityEngine;
using UnityEngine.UI;
using System.Text;
using System.Collections;
using System.Collections.Generic;

public class THETAOSC : MonoBehaviour {

	void Start () {
		StartCoroutine(StartThetaS());
	}

	IEnumerator StartThetaS () {
		string url = "http://192.168.1.1/osc/info";
		WWW www = new WWW(url);
		yield return www;
		Debug.Log(www.text);

		Dictionary<string, string> header = new Dictionary<string, string>();
		url = "http://192.168.1.1/osc/commands/execute";
		string jsonStr = "{\"name\": \"camera.startSession\"}";
		byte[] postBytes = Encoding.Default.GetBytes (jsonStr);
		www = new WWW (url, postBytes, header);
		yield return www;
		JsonNode json = JsonNode.Parse(www.text);
		string sessionId = json["results"]["sessionId"].Get<string>();
		Debug.Log(sessionId);

		jsonStr = "{\"name\": \"camera.takePicture\", \"parameters\": {\"sessionId\": \"" + sessionId + "\"}}";
		postBytes = Encoding.Default.GetBytes (jsonStr);
		www = new WWW (url, postBytes, header);
		yield return www;
		Debug.Log(www.text);

		string fileUri = "";
		url = "http://192.168.1.1/osc/state";
		jsonStr = "{}";
		postBytes = Encoding.Default.GetBytes (jsonStr);
		while(fileUri == "") {
			www = new WWW (url, postBytes, header);
			yield return www;
			Debug.Log(www.text);
			json = JsonNode.Parse(www.text);
			fileUri = json["state"]["_latestFileUri"].Get<string>();
		}
		Debug.Log(fileUri);

		//Même si fileUri est obtenu, le processus peut ne pas être terminé, alors attendez un moment
		yield return new WaitForSeconds(3); 

		url = "http://192.168.1.1/osc/commands/execute";
		jsonStr = "{\"name\": \"camera.getImage\", \"parameters\": {\"fileUri\": \"" + fileUri + "\"}}";
		postBytes = Encoding.Default.GetBytes (jsonStr);
		www = new WWW (url, postBytes, header);
		yield return www;

		//Afficher en image brute pour confirmation
		RawImage rawImage = GetComponent<RawImage>();
		rawImage.texture = www.textureNonReadable;
		rawImage.SetNativeSize();

		jsonStr = "{\"name\": \"camera.closeSession\", \"parameters\": {\"sessionId\": \"" + sessionId + "\"}}";
		postBytes = Encoding.Default.GetBytes (jsonStr);
		www = new WWW (url, postBytes, header);
		yield return www;
		Debug.Log(www.text);
	}
}

Unreal Engine 4 (prévu)

Summary En utilisant l'API compatible OSC de THETA S, j'ai en fait essayé de déplacer le flux de prise de vue et de collecte d'images et comment accéder à l'API dans chaque environnement. Vous pouvez également définir les options de prise de vue pour l'appareil photo de la même manière, donc je pense que vous pouvez jouer avec. J'espère que ce sera une référence et une opportunité!

Recommended Posts

API RICOH THETA S en plusieurs langues.
Parlez de l'API d'acquisition du temps dans le langage de programmation
API Evernote en Python
HMAC en plusieurs langues
API C en Python 3