- Since
- 1.3 1.2 2.4
- See also
-
画像データを送受信します。 画像のリサイズ、圧縮などの処理をサーバー側で行う機能があります。
送信
C++ 画像データを表す型として webcface::ImageFrame があります。 生の画像データがあればImageFrameのコンストラクタに渡すことができます。
unsigned char data[640 * 480 * 3];
(ver1.3から追加) 画像データ
Definition image_frame.h:101
Size sizeWH(int width, int height)
幅 × 高さ でサイズを指定
Definition image_frame.h:48
ImageColorModeとしては gray
(8bitグレースケール)、rgb
(8bit×3)、bgr
(8bit×3)、rgba
(8bit×4)、bgra
(8bit×4) が扱えます。
- Note
- ImageFrameオブジェクト内部では画像データは
shared_ptr<vector<unsigned char>>
で保持されます。
ImageFrameのコンストラクタにdataのポインタを渡した場合、 dataの内容(width × height × channels() バイト)がすべてコピーされます。
ImageFrameをコピーした場合は画像データが共有されます(コピーされません)。
Client::image からImageオブジェクトを作り、 Image::set() でImageFrame型の画像データを代入し、Client::sync()することで送信されます。 set() の代わりに代入演算子(Image::operator=)でも同様のことができます。
wcli.image("hoge").set(frame);
wcli.image("hoge") = frame;
JavaScript 画像データを表す型として ImageFrame があります。 生の画像データがあればImageFrameのコンストラクタに渡すことができます。
import { ImageFrame, imageColorMode } from "webcface";
const data: ArrayBuffer = /* 640 * 480 * 3 バイトのデータ... */;
// 画像サイズは 横, 縦 で指定
const frame: ImageFrame = new ImageFrame(640, 480, data, imageColorMode.rgb);
imageColorModeとしては gray
(8bitグレースケール)、rgb
(8bit×3)、bgr
(8bit✕3)、rgba
(8bit✕4)、bgra
(8bit✕4) が扱えます。
Client.image からImageオブジェクトを作り、 Image.set() でImageFrame型の画像データを代入し、Client.sync()することで送信されます。
wcli.image("hoge").set(frame);
Python 画像データを表す型として webcface.ImageFrame があります。 生の画像データがあればImageFrameのコンストラクタに渡すことができます。
from webcface import ImageFrame, ImageColorMode, ImageCompressMode
frame = ImageFrame(640, 480, data, ImageColorMode.RGB, ImageCompressMode.RAW)
ImageColorModeとして GRAY
(8bitグレースケール)、RGB
(8bit×3)、BGR
(8bit✕3)、RGBA
(8bit✕4)、BGRA
(8bit✕4) が扱えます。
Client.image からImageオブジェクトを作り、 Image.set() でImageFrame型の画像データを代入し、Client.sync()することで送信されます。
wcli.image("hoge").set(frame)
外部ライブラリの利用
- OpenCV (C++) ImageFrame → cv::Mat
cv::Mat img_mat(img_frame.rows(), img_frame.cols(), CV_8UC3, img_frame.data().data());
cv::Mat → ImageFrame assert(img_mat.depth() == CV_8U);
if (img_mat.isContinuous()) {
} else {
for (int i = 0; i < mat.rows; ++i) {
std::memcpy(&img_frame.
at(i, 0, 0), mat.ptr<
unsigned char>(i),
mat.cols * mat.channels());
}
}
const unsigned char & at(int row, int col, int ch=0) const
画像の要素にアクセス
Definition image_frame.h:257
Size sizeHW(int height, int width)
高さ × 幅 でサイズを指定
Definition image_frame.h:55
- Numpy (Python) ImageFrame → ndarray
img_np = img_frame.numpy()
assert img_np.shape == (height, width, img_frame.channels())
ndarray → ImageFrame
assert img_np.dtype == np.uint8
assert img_np.shape == (height, width, 3)
img_frame = ImageFrame.from_numpy(img_np, ImageColorMode.BGR)
C++ OpenCVと相互変換できるImageFrame (〜ver1.11まで)
画像データを表す型として webcface::ImageFrame があります。 cv::Mat形式 (CV_8UC1
,CV_8UC3
,CV_8UC4
フォーマットのみ) の画像データをImageFrameのコンストラクタに渡すことができます。
ImageColorModeとしては gray
(8bitグレースケール)、rgb
(8bit×3)、bgr
(8bit×3)、rgba
(8bit×4)、bgra
(8bit×4) から元の画像データのフォーマットを指定してください。
- Note
- ImageFrameオブジェクト内部では画像データは
shared_ptr<vector<unsigned char>>
で保持されます。
ImageFrameのコンストラクタでcv::Mat内部の画像データがすべてコピーされます。
ImageFrameをコピーした場合は画像データが共有されます(コピーされません)。
ImageFrameをImageにsetして送信します。
wcli.image("hoge").set(frame);
(C++のみ) set() の代わりに代入演算子(Image::operator=)でも同様のことができます。
wcli.image("hoge") = frame;
ImageFrame::mat() でcv::Mat形式に変換できますが、その場合画像データ本体はImageFrameが保持しているためcv::Mat画像を使う間ImageFrameオブジェクトが破棄されないようにしてください。 (例えば wcli.member("foo").image("hoge").get().mat()
はできません)
また、Imageを一度変数に入れて使うと、 Image::mat() で直接cv::Matに変換することもできます (この場合データ本体はImageが保持しています)
while(true){
cv::Mat data = image.mat();
}
(ver1.3から追加) 画像の送受信データを表すクラス
Definition image.h:20
- Note
- 圧縮された画像が入ったImageFrameをcv::Matに変換すると画像をデコードして返します。
受信
C++ Member::image() でImageクラスのオブジェクトが得られ、 Image::request() で画像のリクエストをした後 Image::tryGet() で受信した画像を取得できます。
例えばfoo
というクライアントのhoge
という名前のデータを取得したい場合は次のようにします。
wcli.member("foo").image("hoge").request();
while(true){
std::optional<webcface::ImageFrame> frame = wcli.member("foo").image("hoge").tryGet();
if(frame){
}
}
- リクエストした画像を受信するまでの間tryGet()はstd::nulloptを返します。
- get() を使うとstd::nulloptの代わりに空のImageFrameを返します。
- (ImageFrame::empty() で空かどうかを判別できます)
- ImageをImageFrameにキャストすることでも get() と同様に画像が得られます。
- request() を1度も呼ばずに tryGet() や get() した場合、デフォルトのオプションで(元画像のフォーマットで)リクエストされます。
- ImageFrameの中のデータには dataPtr() (
shared_ptr<vector<unsigned char>>
型)、 data() (vector<unsigned char>&
型)、 at(y, x, ch) (unsigned char &
型) でアクセスできます。
request() の引数に画像のサイズと色モードを指定すると、サーバー側で指定したフォーマットに変換されたものが取得できます。
また送信側が高頻度で画像を更新する場合、フレームレートを指定するとそれより遅い頻度で受信させることもできます。
wcli.member("foo").image("hoge").request(sizeWH(64, 48),
wcli.member("foo").image("hoge").request(sizeWH(64, std::nullopt),
また jpeg, png, webp に圧縮した画像をリクエストすることでも通信量を減らすことができます。 詳細は webcface::Image::request() を参照
wcli.member("foo").image("hoge").request(sizeWH(64, 48),
5);
圧縮された画像の場合 dataPtr() または data() を使ってバイナリデータとして取得できますが、 at() での要素アクセスはできません。
JavaScript Member.image() でImageクラスのオブジェクトが得られ、 Image.request() で画像のリクエストをした後 Image.tryGet() で受信した画像を取得できます。
例えばfoo
というクライアントのhoge
という名前のデータを取得したい場合は次のようにします。
wcli.member("foo").image("hoge").request({}); // 何も指定しない→元画像をそのまま受信
while(true){
const frame: ImageFrame | null = wcli.member("foo").image("hoge").tryGet();
if(frame){
//...
}
}
- リクエストした画像を受信するまでの間tryGet()はnullを返します。
- Image.get() を使うとnullの代わりに空のImageFrameを返します。
- request() を1度も呼ばずに tryGet() や get() した場合、デフォルトのオプションで(元画像のフォーマットで)リクエストされます。
- 受信した画像は ImageFrame.data から取得できます。
request() の引数に画像のサイズと色モードを指定すると、サーバー側で指定したフォーマットに変換されたものが取得できます。
また送信側が高頻度で画像を更新する場合、フレームレートを指定するとそれより遅い頻度で受信させることもできます。
request() の引数については ImageReq を参照
// 64x48にリサイズ、さらに要素をRGBの順にし、1秒に5枚まで受信する
wcli.member("foo").image("hoge").request({
width: 64,
height: 48,
colorMode: imageColorMode.rgb,
frameRate: 5,
});
// 幅が64になるようリサイズ(縦横比を維持)
wcli.member("foo").image("hoge").request({
width: 64,
colorMode: imageColorMode.rgb,
});
// サイズは元画像のままグレースケール
wcli.member("foo").image("hoge").request({
colorMode: imageColorMode.gray,
});
また jpeg, png, webp に圧縮した画像をリクエストすることでも通信量を減らすことができます。
// 64x48にリサイズ、さらにjpeg圧縮、1秒に5枚まで受信する
wcli.member("foo").image("hoge").request({
width: 64,
height: 48,
compressMode: imageCompressMode.jpeg,
quality: 50,
frameRate: 5,
});
圧縮された画像の場合も ImageFrame.data からバイナリデータとして取得できます。
また、 ImageFrame.toBase64() でbase64にエンコードすることができます。
Python Member.image() でImageクラスのオブジェクトが得られ、 Image.request() で画像のリクエストをした後 Image.try_get() で受信した画像を取得できます。
例えばfoo
というクライアントのhoge
という名前のデータを取得したい場合は次のようにします。
wcli.member("foo").image("hoge").request()
while True:
frame = wcli.member("foo").image("hoge").try_get()
if frame is not None:
- リクエストした画像を受信するまでの間try_get()はNoneを返します。
- Image.get() を使うとNoneの代わりに空のImageFrameを返します。
- (ImageFrame.empty() で空かどうかを判別できます)
- request() を1度も呼ばずに try_get() や get() した場合、デフォルトのオプションで(元画像のフォーマットで)リクエストされます。
- 受信した画像は ImageFrame.data, ImageFrame.numpy() から取得できます。
request() の引数に画像のサイズと色モードを指定すると、サーバー側で指定したフォーマットに変換されたものが取得できます。
また送信側が高頻度で画像を更新する場合、フレームレートを指定するとそれより遅い頻度で受信させることもできます。
wcli.member("foo").image("hoge").request(
width=64,
height=48,
color_mode=ImageColorMode.RGB,
frame_rate=5,
)
wcli.member("foo").image("hoge").request(
width=64,
color_mode=ImageColorMode.RGB,
)
wcli.member("foo").image("hoge").request(
color_mode=ImageColorMode.GRAY,
)
また jpeg, png, webp に圧縮した画像をリクエストすることでも通信量を減らすことができます。
wcli.member("foo").image("hoge").request(
width=64,
height=48,
compress_mode=ImageCompressMode.JPEG,
quality=50,
frame_rate=5,
)
圧縮された画像の場合も ImageFrame.data からバイナリデータとして取得できますが、 ImageFrame.numpy() は使えません。
Entry, Event
いずれも使い方は Value と同様なのでそちらを参照してください