[英]Java render webcam's image take too much CPU
I'm writing an application which connect and stream webcam video. 我正在编写一个连接和流式传输网络摄像头视频的应用程序。 To do that, I use Sarxos webcam library (link here ) to get default webcam, then use WebcamPanel to draw image.
为此,我使用Sarxos网络摄像头库( 此处链接)获取默认网络摄像头,然后使用WebcamPanel绘制图像。 The problem arose when I delivered the app to my customer, they tested it on an old machine and complained the app took too much CPU.
当我将应用交付给客户时,问题就出现了,他们在旧计算机上对其进行了测试,并抱怨该应用占用了过多的CPU。
I never noticed that before, and when I tested it again, to my surprise, the app took around 33% CPU, which is too much for a simple app which only connect webcam and draw image with 30 FPS. 我之前从未注意到,当我再次对其进行测试时,令我惊讶的是,该应用程序占用了大约33%的CPU,对于仅连接摄像头并以30 FPS绘制图像的简单应用程序来说,这实在太多了。 Here is my programming environment: Windows 7 64bit, CoreI5-4460 CPU (3.2-3.4Ghz), Zotac Geforce GTX 650 Ti, Java 7u45.
这是我的编程环境:Windows 7 64bit,CoreI5-4460 CPU(3.2-3.4Ghz),Zotac Geforce GTX 650 Ti,Java 7u45。
I have tested to point out which part took the most CPU, and it is the rendering. 我测试指出哪个部分占用了最多的CPU,这就是渲染。 If I fetch webcam images only but not draw them, the CPU takes 6-7%, but when I render them, the CPU jumps to 30-33%.
如果仅获取而不是绘制网络摄像头图像,则CPU占用6-7%,但是渲染时,CPU跳至30-33%。 I took a look in to WebcamPanel class to see maybe something is wrong with them, but so far I found nothing.
我查看了WebcamPanel类,以查看它们是否有问题,但到目前为止我什么都没找到。 The draw method is as below:
绘制方法如下:
@Override
public void paintImage(WebcamPanel owner, BufferedImage image, Graphics2D g2) {
assert owner != null;
assert image != null;
assert g2 != null;
int pw = getWidth();
int ph = getHeight();
int iw = image.getWidth();
int ih = image.getHeight();
Object antialiasing = g2.getRenderingHint(KEY_ANTIALIASING);
Object rendering = g2.getRenderingHint(KEY_RENDERING);
g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_OFF);
g2.setRenderingHint(KEY_RENDERING, VALUE_RENDER_SPEED);
g2.setBackground(Color.BLACK);
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, pw, ph);
// resized image position and size
int x = 0;
int y = 0;
int w = 0;
int h = 0;
switch (drawMode) {
case NONE:
w = image.getWidth();
h = image.getHeight();
break;
case FILL:
w = pw;
h = ph;
break;
case FIT:
double s = Math.max((double) iw / pw, (double) ih / ph);
double niw = iw / s;
double nih = ih / s;
double dx = (pw - niw) / 2;
double dy = (ph - nih) / 2;
w = (int) niw;
h = (int) nih;
x = (int) dx;
y = (int) dy;
break;
}
if (resizedImage != null) {
resizedImage.flush();
}
if (w == image.getWidth() && h == image.getHeight() && !mirrored) {
resizedImage = image;
} else {
GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = genv.getDefaultScreenDevice().getDefaultConfiguration();
Graphics2D gr = null;
try {
resizedImage = gc.createCompatibleImage(pw, ph);
gr = resizedImage.createGraphics();
gr.setComposite(AlphaComposite.Src);
for (Map.Entry<RenderingHints.Key, Object> hint : imageRenderingHints.entrySet()) {
gr.setRenderingHint(hint.getKey(), hint.getValue());
}
gr.setBackground(Color.BLACK);
gr.setColor(Color.BLACK);
gr.fillRect(0, 0, pw, ph);
int sx1, sx2, sy1, sy2; // source rectangle coordinates
int dx1, dx2, dy1, dy2; // destination rectangle coordinates
dx1 = x;
dy1 = y;
dx2 = x + w;
dy2 = y + h;
if (mirrored) {
sx1 = iw;
sy1 = 0;
sx2 = 0;
sy2 = ih;
} else {
sx1 = 0;
sy1 = 0;
sx2 = iw;
sy2 = ih;
}
gr.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null);
} finally {
if (gr != null) {
gr.dispose();
}
}
}
g2.drawImage(resizedImage, 0, 0, null);
if (isFPSDisplayed()) {
String str = String.format("FPS: %.1f", webcam.getFPS());
int sx = 5;
int sy = ph - 5;
g2.setFont(getFont());
g2.setColor(Color.BLACK);
g2.drawString(str, sx + 1, sy + 1);
g2.setColor(Color.WHITE);
g2.drawString(str, sx, sy);
}
if (isImageSizeDisplayed()) {
String res = String.format("%d\u2A2F%d px", iw, ih);
FontMetrics metrics = g2.getFontMetrics(getFont());
int sw = metrics.stringWidth(res);
int sx = pw - sw - 5;
int sy = ph - 5;
g2.setFont(getFont());
g2.setColor(Color.BLACK);
g2.drawString(res, sx + 1, sy + 1);
g2.setColor(Color.WHITE);
g2.drawString(res, sx, sy);
}
if (isDisplayDebugInfo()) {
if (lastRepaintTime < 0) {
lastRepaintTime = System.currentTimeMillis();
} else {
long now = System.currentTimeMillis();
String res = String.format("DEBUG: repaints per second: %.1f", (double) 1000 / (now - lastRepaintTime));
lastRepaintTime = now;
g2.setFont(getFont());
g2.setColor(Color.BLACK);
g2.drawString(res, 6, 16);
g2.setColor(Color.WHITE);
g2.drawString(res, 5, 15);
}
}
g2.setRenderingHint(KEY_ANTIALIASING, antialiasing);
g2.setRenderingHint(KEY_RENDERING, rendering);
}
I have tried quite a lot of things to optimal my rendering, but there's nothing work. 我已经尝试了很多方法来优化我的渲染,但是没有任何效果。 The things I tried:
我尝试过的事情:
I'm considering to change to an OpenGL library to render the image, but it will be the last option, because I've no knowledge about OpenGL, and I think Java2D is more than enough for my application. 我正在考虑更改为OpenGL库以渲染图像,但这将是最后的选择,因为我不了解OpenGL,而且我认为Java2D对我的应用程序绰绰有余。 Can anyone help me solve this problem?
谁能帮我解决这个问题?
After test with various things, include render webcam's images using OpenGL (took me too much time since I have to learned OpenGL from scratch), I have found the solution. 经过各种测试,包括使用OpenGL渲染网络摄像头的图像(花了我太多时间,因为我不得不从头开始学习OpenGL),我找到了解决方案。 These are the things I did:
这些是我所做的事情:
After that, my CPU percentage for the app dropped from 33% to 11%. 之后,我的应用程序CPU百分比从33%下降到11%。 Hope this will have someone who runs to the same problem with me.
希望这会有一个遇到我同样问题的人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.