だいぶ時間があきましたが、isightで画像をキャプチャーして
ウインドウに表示するサンプルコードできました。
画像サイズは320×240です。サイズを大きくしてもいいですが、
処理が遅くなるので今後の課題です。
おまけで画像を1)グレイスケールにする関数、
2)RGBのRとBを入れ替える関数も用意してみました。
画像処理する方の参考まで。
次回は顔検出あたりにトライでしょうか。
コード以下>>
package test;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.WritableRaster;
import quicktime.QTSession;
import quicktime.qd.PixMap;
import quicktime.qd.QDGraphics;
import quicktime.qd.QDRect;
import quicktime.std.StdQTConstants;
import quicktime.std.sg.SGVideoChannel;
import quicktime.std.sg.SequenceGrabber;
import quicktime.util.RawEncodedImage;
import viewer.ImageViewer;
public class VideoCapture {
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int TIME_PER_FRAME = 67;
private SequenceGrabber grabber;
private SGVideoChannel channel;
private RawEncodedImage rowEncodedImage;
private int width;
private int height;
private int videoWidth;
private int[] pixels;
private BufferedImage image;
private WritableRaster raster;
public void proccess() {
try {
ImageViewer viewer = new ImageViewer(WIDTH, HEIGHT);
while (true) {
long start = System.currentTimeMillis();
// イメージをビュアーにセット
image = (BufferedImage) getNextImage();
// 画像処理
// inverseColor();
// grayScale();
viewer.setImage(image);
long time = System.currentTimeMillis() - start;
// キャプチャー、プレビューを時間TIME_PER_FRAMEで繰り返す
if (time < TIME_PER_FRAME) {
try {
Thread.sleep(TIME_PER_FRAME - time);
} catch (Exception e) {
System.err.println(e);
}
}
System.out.println("Frame Time : "
+ (System.currentTimeMillis() - start));
}
} catch (Exception e) {
// TODO: handle exception
}
}
public static void main(String[] args) {
try {
new VideoCapture(WIDTH, HEIGHT);
} catch (Exception e) {
System.out.println(e);
}
}
/**
* 画像の座標x,y,のrgb値を配列で返します
*
* @param x
* @param y
* @return
*/
public int[] getRGB(int x, int y) {
int val = image.getRGB(x, y);
int r = val >> 16 & 0xff;
int g = val >> 8 & 0xff;
int b = val & 0xff;
int[] rgb = { r, g, b };
return rgb;
}
/**
* 各ピクセルのrとbを反転します
*/
public void inverseColor() {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int[] rgb = getRGB(x, y);
int val = rgb[0] | rgb[1] << 8 | rgb[2] << 16;
image.setRGB(x, y, val);
}
}
}
/**
* 画像をグレースケールに変換します
*/
public void grayScale() {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int[] rgb = getRGB(x, y);
int val = (int) (rgb[0] * 0.2989 + rgb[1] * 0.5866 + rgb[2] * 0.1144);
int gray = val | val << 8 | val << 16;
image.setRGB(x, y, gray);
}
}
}
public VideoCapture(int width, int height) throws Exception {
this.width = width;
this.height = height;
try {
QTSession.open();
QDRect bounds = new QDRect(width, height);
QDGraphics graphics = new QDGraphics(bounds);
grabber = new SequenceGrabber();
grabber.setGWorld(graphics, null);
channel = new SGVideoChannel(grabber);
channel.setBounds(bounds);
channel.setUsage(StdQTConstants.seqGrabPreview);
grabber.prepare(true, false);// プレビューON、録画OFF
grabber.startPreview();// プレビューをスタート
PixMap pixmap = graphics.getPixMap();
rowEncodedImage = pixmap.getPixelData();
videoWidth = width + (rowEncodedImage.getRowBytes() - width * 4)
/ 4;
pixels = new int[videoWidth * height];
image = new BufferedImage(videoWidth, height,
BufferedImage.TYPE_INT_RGB);
raster = WritableRaster.createPackedRaster(DataBuffer.TYPE_INT,
videoWidth, height, new int[] { 0x00ff0000, 0x0000ff00,
0x000000ff }, null);
raster.setDataElements(0, 0, videoWidth, height, pixels);
image.setData(raster);
// 画像処理
proccess();
} catch (Exception e) {
QTSession.close();
throw e;
}
}
public void dispose() {
try {
grabber.stop();
grabber.release();
grabber.disposeChannel(channel);
image.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
QTSession.close();
}
}
public void getNextPixels(int[] pixels) throws Exception {
grabber.idle();
rowEncodedImage.copyToArray(0, pixels, 0, pixels.length);
}
public Image getNextImage() throws Exception {
grabber.idle();
rowEncodedImage.copyToArray(0, pixels, 0, pixels.length);
raster.setDataElements(0, 0, videoWidth, height, pixels);
image.setData(raster);
return image;
}
}
ウインドウに表示するサンプルコードできました。
画像サイズは320×240です。サイズを大きくしてもいいですが、
処理が遅くなるので今後の課題です。
おまけで画像を1)グレイスケールにする関数、
2)RGBのRとBを入れ替える関数も用意してみました。
画像処理する方の参考まで。
次回は顔検出あたりにトライでしょうか。
コード以下>>
package test;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.WritableRaster;
import quicktime.QTSession;
import quicktime.qd.PixMap;
import quicktime.qd.QDGraphics;
import quicktime.qd.QDRect;
import quicktime.std.StdQTConstants;
import quicktime.std.sg.SGVideoChannel;
import quicktime.std.sg.SequenceGrabber;
import quicktime.util.RawEncodedImage;
import viewer.ImageViewer;
public class VideoCapture {
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int TIME_PER_FRAME = 67;
private SequenceGrabber grabber;
private SGVideoChannel channel;
private RawEncodedImage rowEncodedImage;
private int width;
private int height;
private int videoWidth;
private int[] pixels;
private BufferedImage image;
private WritableRaster raster;
public void proccess() {
try {
ImageViewer viewer = new ImageViewer(WIDTH, HEIGHT);
while (true) {
long start = System.currentTimeMillis();
// イメージをビュアーにセット
image = (BufferedImage) getNextImage();
// 画像処理
// inverseColor();
// grayScale();
viewer.setImage(image);
long time = System.currentTimeMillis() - start;
// キャプチャー、プレビューを時間TIME_PER_FRAMEで繰り返す
if (time < TIME_PER_FRAME) {
try {
Thread.sleep(TIME_PER_FRAME - time);
} catch (Exception e) {
System.err.println(e);
}
}
System.out.println("Frame Time : "
+ (System.currentTimeMillis() - start));
}
} catch (Exception e) {
// TODO: handle exception
}
}
public static void main(String[] args) {
try {
new VideoCapture(WIDTH, HEIGHT);
} catch (Exception e) {
System.out.println(e);
}
}
/**
* 画像の座標x,y,のrgb値を配列で返します
*
* @param x
* @param y
* @return
*/
public int[] getRGB(int x, int y) {
int val = image.getRGB(x, y);
int r = val >> 16 & 0xff;
int g = val >> 8 & 0xff;
int b = val & 0xff;
int[] rgb = { r, g, b };
return rgb;
}
/**
* 各ピクセルのrとbを反転します
*/
public void inverseColor() {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int[] rgb = getRGB(x, y);
int val = rgb[0] | rgb[1] << 8 | rgb[2] << 16;
image.setRGB(x, y, val);
}
}
}
/**
* 画像をグレースケールに変換します
*/
public void grayScale() {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int[] rgb = getRGB(x, y);
int val = (int) (rgb[0] * 0.2989 + rgb[1] * 0.5866 + rgb[2] * 0.1144);
int gray = val | val << 8 | val << 16;
image.setRGB(x, y, gray);
}
}
}
public VideoCapture(int width, int height) throws Exception {
this.width = width;
this.height = height;
try {
QTSession.open();
QDRect bounds = new QDRect(width, height);
QDGraphics graphics = new QDGraphics(bounds);
grabber = new SequenceGrabber();
grabber.setGWorld(graphics, null);
channel = new SGVideoChannel(grabber);
channel.setBounds(bounds);
channel.setUsage(StdQTConstants.seqGrabPreview);
grabber.prepare(true, false);// プレビューON、録画OFF
grabber.startPreview();// プレビューをスタート
PixMap pixmap = graphics.getPixMap();
rowEncodedImage = pixmap.getPixelData();
videoWidth = width + (rowEncodedImage.getRowBytes() - width * 4)
/ 4;
pixels = new int[videoWidth * height];
image = new BufferedImage(videoWidth, height,
BufferedImage.TYPE_INT_RGB);
raster = WritableRaster.createPackedRaster(DataBuffer.TYPE_INT,
videoWidth, height, new int[] { 0x00ff0000, 0x0000ff00,
0x000000ff }, null);
raster.setDataElements(0, 0, videoWidth, height, pixels);
image.setData(raster);
// 画像処理
proccess();
} catch (Exception e) {
QTSession.close();
throw e;
}
}
public void dispose() {
try {
grabber.stop();
grabber.release();
grabber.disposeChannel(channel);
image.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
QTSession.close();
}
}
public void getNextPixels(int[] pixels) throws Exception {
grabber.idle();
rowEncodedImage.copyToArray(0, pixels, 0, pixels.length);
}
public Image getNextImage() throws Exception {
grabber.idle();
rowEncodedImage.copyToArray(0, pixels, 0, pixels.length);
raster.setDataElements(0, 0, videoWidth, height, pixels);
image.setData(raster);
return image;
}
}
。