JAVAにおける画像のJPEG保存の高速化
- JAVAにおいて、画像のJPEG保存を高速化する方法を探しています。
- 現在USBWebカメラを利用し、画像処理をした後に画像をJPEG形式で保存するプログラムを作成しています。
- 保存処理が非常に重く、現状のノートPCでは一画像の保存に20ms以上かかってしまいます。処理の高速化方法を教えてください。
- ベストアンサー
JAVAにおける画像のJPEG保存の高速化
現在USBWebカメラを利用し、画像処理をしたのちに画像をJPEG形式で保存するというプログラムを作成しています。 入力画像ビットマップデータをINT配列化⇒画像処理⇒INT配列をBufferedImageに変換⇒JPEGで保存 という流れです。 このとき、以下のコードでBufferedImageをJPEGで保存しています。 public void saveJpgbuf(BufferedImage ssimg ,String fname ) throws IOException { //ImageIO.setUseCache(true);//プログラムの初めで実行済み ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next(); ImageOutputStream out = ImageIO.createImageOutputStream(new File("c:\\"+fname + ".jpg")); writer.setOutput(out); writer.write(ssimg); out.close(); } しかし、この処理が非常に重いようで、現状のノートPC(Corei5 2.56GHz)では一画像の保存に20msはかかってしまうようです。 保存先をramdiskに変えても17msはかかります。 他の処理と比べてこの保存処理のコストが非常に高く、全体のパフォーマンスを低下させています。 このような処理を高速化できる方法はありませんでしょうか?
- nightzan
- お礼率40% (4/10)
- Java
- 回答数5
- ありがとう数4
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
(追記) あと、そもそもリアルタイムの画像処理はデータ量や計算量が多すぎてソフトウェアではなく専用のハードウェアに処理させるのが一般的だと思います。 つまり、ソフトウェアでやろうとしていること自体に無理があると思います。3Dゲームなどもハードウェア処理のおかげで秒30フレーム以上で処理ができるわけで、ソフトウェアでやれば秒10フレームでればいいということもあります。 ソフトウェアで処理を行う場合、入力画像の解像度を下げることや秒あたりのフレーム数を減らさざるを得ません。基本的に高性能なマシンを使用することや、CPUアーキテクチャとの相性も考慮する必要があります。 Intel の CPU は互換性に優れていると言えるが、時代遅れとも言えるかもしれない。(アーキテクチャが)と、まだまだ勉強不足ながらそんな印象を最近受けました。 あとは、画像圧縮処理を高速化することですかね。こんなのありました。 http://jpn.nec.com/press/201211/20121105_03.html まあ、ご参考までに。
その他の回答 (4)
- kmee
- ベストアンサー率55% (1857/3366)
JPEGにしないで、ベタに出力したらどうなるでしょう? 読み書きの速度と圧縮速度のどちらが早いか、によりますが。RAMディスクに出力すれば、早いかもしれません
- corokorocoro
- ベストアンサー率29% (63/211)
>すでにマルチスレッド化されており、画像処理後のBufferedImageを他のスレッドに受け渡し、他のスレッドでJPEG保存を行っています。 だったらもうその処理だけC/C++でネイティブ化(Windowsならdll)して作る。
お礼
ありがとうございます。 もうこれ以上はJAVAでは不可能ということですかね・・・。 C等で一部処理を行う必要があるなら、いっそOpenCV等に移植を検討してみます。
- OrangeCup150
- ベストアンサー率62% (109/174)
いや、ちょっと、秒あたり何フレーム処理させようとしているの? 20ms なら秒あたり50フレーム分はできるし・・・。 ハイスピードカメラでも作ろうとしているの? (http://ja.wikipedia.org/wiki/ハイスピードカメラ) そもそも、あなたの使っているUSBWebカメラの性能はいくつですか? http://www.amazon.co.jp/dp/B002J4UA9G/ カメラ・最大フレームレート : ~1280×720ピクセル時 : 30fps、、1600×1200ピクセル時 : 10fps、2048×1536ピクセル時 : 10fps 普通のカメラなら秒30フレームですよ!! 本題 タイマを使って秒30フレームでカメラの画像を取得するように入力系を設計し直すのが適当と思います。 ただ、タイマは精度に注意が必要ですね・・・。 タイマの精度が問題ないか事前にテストして見てください。
お礼
ありがとうございます。 秒あたりの処理フレーム数については以下の理由から早ければ早いほどいいのです。 (1)今後60FPSのUSB接続のカメラ(業務用の内視鏡や眼球カメラ等を含む)、を接続するかもしれない。 (2)現在の私の研究では 1フレームの1枚の画像から4枚の画像を生成し、それを連ねた動画にする、という処理をしています。 そのため、入力は15FPSでもよいのですが、出力は60 FPSの速度で保存できなければ、バッファに蓄積され続けてしまうのです。 ちなみに画像処理部は1フレーム取得から4フレーム分のデータ生成までで約60msで終わります。 とりあえず15FPSでJPEGファイルを保存して、そのあと画像処理という風にすればもちろん解決するのですが、それだとリアルタイム性に欠けるのです。
- corokorocoro
- ベストアンサー率29% (63/211)
マルチスレッド化して画像処理をメイン処理と切り離して裏で処理させて見た目的だけでも処理が止まったような状態ではなくしておく。
お礼
ありがとうございます。 が、すみません。説明が足りませんでした。 すでにマルチスレッド化されており、画像処理後のBufferedImageを他のスレッドに受け渡し、他のスレッドでJPEG保存を行っています。 このとき、画像処理と並列で行っているので、処理時間は20msより長くかかっています。 このJPEG保存の速度が遅いために、保持するBufferedImageが多くなりすぎてメモリが一杯になってしまうのです。
関連するQ&A
- 任意の文字列をJAVAで画像化
表題にある通り任意の文字列をJAVAで画像化したいと思い 下記サンプルを検索して見つけたのですが作成される画像は 真っ白な画像で文字列は表示されませんでした。 任意の文字列を画像として出力するにはどうすればよいでしょうか。 import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; public class Test5 { public static void main(String[] args) { String str = "abc123"; new Test5().Create(str); System.out.println(str); } public void Create(String str) { int w=60; int h=17; try { //受け取った文字列を画像化 BufferedImage image=new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB); Graphics2D g2d=image.createGraphics(); g2d.setBackground(Color.WHITE); g2d.clearRect(0,0,w,h); g2d.setColor(Color.BLACK); g2d.drawString(str,0,0); ImageIO.write(image, "JPEG", new File("c:\\test.jpg")); } catch(Exception e) { e.printStackTrace(); } } }
- ベストアンサー
- Java
- java 画像変換 加工 サイズ変更
OracleDBからBLOB型の画像データを取得しています。 本来必要のなかった処理なのですが、DBに入っている画像のデータがおかしいらしく、ピクセルとdpiの値を変更しなければなりません。 いろいろと調べてやってみようと思ったのですが、いきづまってしまいました(><) みなさんの力をお貸しください。 内容は、 ・一度DBからそのまま画像を抽出し、ファイルを作成 ・作成したファイルをもう一度BufferedImageに取り込み、サイズ変更処理開始 となっています。 しかし、BufferedImageに取り込む際に、nullが帰ってきてしまい、以降の処理ができません・・・。 また、下記処理はすべてjpgで行っていますが、本当はTiffファイルを作りたいのです。 ImageIOクラスは標準ではTiffは対応していないようなのですが、実際に下記ソースの"jpg"を"tif"に変更しても問題はないのでしょうか? 質問が煩雑で申し訳ないですが、よろしくお願いいたします。 以下ソース抜粋です。 ---------------------------------------------------------------- ImageOutNum = (String)rs.get("IMAGEGRPNO"+i)+"_"+(String)rs.get("IMAGENO"+i); // イメージファイルを作成する。 File imagef = new File(outPath2); if(!(imagef.exists()))imagef.mkdirs(); InputStream inImage = (InputStream)rs.get("IMAGEFILE"+i); if (inImage != null) { FileOutputStream outImage = new FileOutputStream(outPath2 + ImageOutNum + ".jpg"); //画像書き込み int j; while ((j = inImage.read()) != -1) { outImage.write(j); } // 解放 outImage.close(); //イメージ変更処理 InputStream orgImageFile = null; orgImageFile = new FileInputStream(outPath2 + ImageOutNum + ".jpg"); BufferedImage orgImage = ImageIO.read(orgImageFile);//ここでorgImageにnullが返されてしまいます。 int width = 640; int height = (int)(((double)width / orgImage.getWidth()) * (double)orgImage.getHeight()); BufferedImage resizeImage = new BufferedImage(width, height, orgImage.getType()); // ここからリサイズ処理 AffineTransformOp ato = null; ato = new AffineTransformOp( AffineTransform.getScaleInstance((double)width / orgImage.getWidth(),(double) height / orgImage.getHeight()),null); ato.filter(orgImage, resizeImage); // ここまでリサイズ処理 ImageOutputStream imageStream = ImageIO.createImageOutputStream(new File(outPath2 + ImageOutNum + ".jpg")); ImageWriter writer = null; Iterator it = (Iterator) ImageIO.getImageWritersByFormatName("jpg"); writer = (ImageWriter) it.next(); writer.setOutput(imageStream); JPEGImageWriteParam jpgWriter = new JPEGImageWriteParam(Locale.getDefault()); jpgWriter.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); jpgWriter.setCompressionQuality(1f); writer.write(null, new IIOImage(resizeImage, null, null), jpgWriter); imageStream.flush(); writer.dispose(); imageStream.close();
- 締切済み
- Java
- javaで画像を表示したのですが、変です。
画像をのせたのですが、表示した画像の透明部分のところに予期しない形で画像が重なってしまいます。 また、ウィンドウのサイズを何回かスクロールしていじると元に戻ります。 文字数の関係ですべてのソースを乗せられないのですが、自作画像クラスだけ記載します。 import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JPanel; public class Layer extends JPanel { BufferedImage image; int x=0,y=0; //表示サイズ int lx=0,ly=0; //表示場所 int originalX,originalY; int startX,startY; Layer(){ } public void p(String imgpath,int lX,int lY,int X,int Y){ x=X;y=Y;lx=lX;ly=lY; image=Imagedraw(imgpath); } public void p(String imgpath,int lX,int lY){ lx=lX;ly=lY; image=Imagedraw(imgpath); x=originalX; y=originalY; setSize(x,y); } public void p(String imgpath){ image=Imagedraw(imgpath); x=originalX; y=originalY; setSize(x,y); } public BufferedImage Imagedraw(String imgpath){ BufferedImage img=null; try{ img = readImage(imgpath); }catch(Exception e){ e.printStackTrace(); } setLocation(lx,ly); setSize(x,y); return img; } public void setLocation(int lX, int lY){ lx=lX;ly=lY; super.setLocation(lx,ly); } public void paint(Graphics g){ //イメージを描画 g.drawImage(image,0,0,x,y,startX,startY,x+startX,y+startY,this); } public BufferedImage readImage(String path) throws IOException{ BufferedImage img; img = ImageIO.read(new File(path)); originalX=img.getWidth(); originalY=img.getHeight(); return img; } } どなたか原因に心当たりのある方、よろしくお願いいたします。 なお、画像はインターネット上での拾いものです。書かれた方には感謝いたします。
- 締切済み
- Java
- 画像を保存するとjpegにはならない
ネット上の画像など個人的に楽しむ目的でいただく場合、右クリックで保存するとjpegイメージではなく、ファイル種類が単なるファイルとしかならず、開くにもieが起動したり、アプリケーションから起動をさせたりしますが、開かない場合があります。msペイントを使いたいときには、msペイントを起動させてから、ファイルを読み込む作業をしなければなりません。最初からjpegかbmpなどで保存できないのでしょうか?この設定は知らない間に変わっていたので、対処の仕方がわかりません。ご存じの方教えてください。
- ベストアンサー
- その他(インターネット・Webサービス)
- jpeg画像が劣化する「保存」とは
「jpeg画像の繰り返し保存は画像の劣化を招く」と、このカテゴリーの書き込みで見かけましたが、この場合の「保存」とは具体的にどのような処理を指すのでしょうか? 過去の質問を見ても回答者の意見がまちまちで、今ひとつよくわかりません。 jpegデータをパソコンに取り込んで、外付けハードディスクに送ったり、CD-Rに焼いたりするだけなら大丈夫なのでしょうか? また、デジカメの画像をメールに添付してもらって、「添付ファイルの保存」でマイピクチャに取り込んだりしていますが、その段階でも既に劣化が発生しているのでしょうか? よろしくお願いいたします。
- ベストアンサー
- その他(インターネット・Webサービス)
- javaのpixelの色の指定に関して
javaの色に関して質問します。 現在PixelGrabberで取得したpixelの中である条件を満たすpixelを指定の色に変換するプログラムを書いているのですが、自分が指定している色と実際に出力される色との違いに悩んでいます。 私が調べた範囲の理解だと pixelはint形式で上の桁から1バイトずつα値(透明度),R,G,Bと表現していると考えています。そこで黒と白を 白=0x00ffffff 黒=0x00000000 と指定しているのですが、真っ黒になってしまいます。指定した色で塗るために知恵を貸してください。お願いします。 ----------------実際のアルゴリズムとデータ---------------- ある閾値よりも濃い色→黒 そうでなければ →白 この値をintの配列にいれ直す 配列からMemoryImageSorceを作る。 bufferedImageに変換して ImageIOのwriteメソッドで書き込む。 ---------------------------結果--------------------------- 添付の画像 グレースケールっぽい画像を二値化
- ベストアンサー
- Java
- JAVAを用いた画像処理
JAVAを用いて、画像を入力しその画像を2値化し出力を行うプログラムを作成したいのですが、どうやらJAVAには、画像を格納するクラス(構造体?)がBufferedImageやImage、Colorなどがあり、その違いがよくわからず困惑しております。 どのような流れで2値化処理を行うのが最も一般的なのでしょうか? また、JAVAを用いた画像処理について勉強できるわかりやすいサイトや本などがあったら教えてほしいです。 回答よろしくお願いします。
- ベストアンサー
- Java
- JAVAアプレットで画像保存
JAVAアプレットで写真画像を呼び出して、その写真上にdrawOvalなどで円を描いて その加工した写真をJPEGで保存したいのですが保存方法がわかりません。 JPEGImageEncoder等も参照しましたが、いまいちよく解りません。 出来ればサンプルプログラムなどあればうれしいのですがよろしくお願いします。
- ベストアンサー
- Java
- JPEG画像の圧縮率について
JPEG画像の圧縮について質問いたします。 画像処理ソフト(Fireworks)のJPEG形式による書き出しでは,品質(圧縮率?)を選べます(Photoshopも同様だった気がします)。この際,最高品質(100)を指定すると,画像の劣化はないのでしょうか。 JPEGは保存のたびに画質が劣化する読んだことがありますが,画像処理ソフトで品質を最高で書き出しや保存すると,画像処理した以外の部分の品質は,元のJPEG画像のままなのでしょうか。 よろしくお願いします。
- ベストアンサー
- グラフィックソフト
- 画像を綺麗に保存したいのですが・・・
ネットでやっているゲームなどの画像をJPEG画像で保管したり、ブログで掲載したいのですが、どうしても綺麗に保存できないのです(ノ◇≦。) いつもPrintScreenキーを押し、Winのペイントに貼り付けて画像サイズを整えJPEG保存しているのですが、保存画像を開いてみると色などにムラができてしまいます。 24ビットbmpで保存し、irfanViewなどのGIF変換ソフトを使ってみてもイマイチ綺麗に保存できていません。 (mixi等のSNSはJPEG画像しか掲載できないので、できればJPEG画像で保存したいのです) 使っている画像処理ソフト(ペイント)が悪いのでしょうか?? ブラウザ画像等を綺麗に保存するのにオススメの方法やソフトがありましたら教えて下さいm(__)m
- ベストアンサー
- 画像・動画・音楽編集
お礼
ありがとうございます。参考になります。 私の研究におけるこの処理は、当初ハードウェアでやろうと検討したら5000万の機械が必要と言われ、ソフトウェアでできたら安く済むな、という経緯がありました。 ソフトウェアで成果が上がれば、専用ハードウェアを頼めるのです。 とりあえずは今あるハードウェア(CPU,GPU,SSD等)をうまく使って解決していきます。