Boost」など、さまざまなカンファレンスを企画・運営しています。BOOKS(コードジン・ブックス)は、CodeZineの連載からカットアップした、開発現場の課題解決に役立つ書籍シリーズです。KB)コンボリューション(畳み込み演算)を画像処理に使うと、画像を滑らかにしたり、シャープにしたりできます。APIを利用して、画像処理の基本となる平滑化、鮮鋭化、およびエッジ検出を実装する方法を解説します。ポストはじめにコンボリューション(Convolution)は数学用語で、日本語では「畳み込み」といいます。掛け算の結果を足し集める演算からなり、コンピュータ処理の得意とするところです。コンボリューションを画像処理に使うと、画像を滑らかにしたり、シャープにしたりできます。掛け算の係数は、3×3などのサイズのマトリックスで指定します。これをオペレータ、フィルタ、マスク、カーネルなどと呼びます。APIには、画像処理でコンボリューションを行うのに便利なConvolveOpやKernelのクラスがあります。基本を学び、ペイント系画像ソフトの一部の機能を自作したい人。1.4.2でも大丈夫です。コンボリューションに使用するオペレータのいろいろコンボリューションは、3×3(一例)のオペレータを原画像に沿って移動させ、オペレータの各要素の値と対応する原画像のピクセル値とを掛け合わせて合計して行います。ここでは、画像処理の目的に応じた各種のオペレータを紹介します。平滑化オペレータ一番単純なのは平滑化オペレータで、3×3の範囲の原画像のピクセル値を平均して、中心のピクセル値として出力します。一種の移動平均を取る操作で、画像は「ぼけ」た状態になります。図1は、オペレータの要素と効果を示したもので、中央が平均化(平滑化)用です。左は、説明のためのもので、実際に使用されることはありませんが、これを使用すると原画像と同じ出力が得られます。右は、「ぼけ」の程度を弱めたもので、中心のピクセルの値に大きな比重を与えています。いずれも、各要素を合計すると1になることに注目してください。平滑化オペレータには、もっと複雑なものもあります。ガウス分布を用い、「ぼけ」の範囲をσ(シグマ)で調整できる7×7や15×15の大きなものです。鮮鋭化オペレータ鮮鋭化オペレータには、原画像に二次微分空間フィルタLaplacian(ラプラシアン)の結果を加算する方式と、アンシャープと呼ばれる、原画像から平滑化(ぼけ)の結果を減算する方法とがあります。アンシャープ方式の方が、ガウス分布による調節ができるので、多く使われています。アンシャープ(Unsharp)は、文字通り訳すと「シャープにしない」ですが、実際は「シャープにする」オペレータです。図2はアンシャープオペレータの原理を示したもので、原画像と平均(平滑化)画像との差分を原画像に上乗せすることにより、変化分を強調します。プログラムでは、アンシャープ方式の最も簡単なものを採用しています。先鋭化オペレータの一つであるアンシャープオペレータの原理エッジ検出オペレータエッジ検出オペレータには、一次微分を用いるものと二次微分を用いるものがあります。分けて検出する必要があります。一次微分方式で有名なものには、Prewitt(プレビィット)とSobel(ゾーベル)がありますが、差はほとんどありません。二次微分はLaplacianを用い、方向性がありませんが感度が高いために、雑音に弱い欠点があります。したがって、これを単独で用いることは少なく、ガウスぼかし(平滑化)と併用します。プログラムでは、一次微分の中では一般的なSobelオペレータを用いています。図3はSobelオペレータの原理をイメージ的に示したもので、右側に黒い部分がある画像部分をコンボリューションすると「4」が得られ、左側に黒い部分があると「-4」が得られます。上下にある場合や、変化がない場合は、コンボリューション結果は「0」になります。このオペレータは、垂直方向のエッジを検出します。右が黒か、左が黒かは、出力の符号で分かります。APIのConvolveOpの場合は、負の出力はカットされますので、オペレータの各要素を反転した(-1を掛けた)、負出力用のオペレータを併用する必要があります。APIによるコンボリューション(平滑化と鮮鋭化)便利な専用APIを使用したコンボリューションは、次のようにして実行します(平滑化の例)。bimg_dest=convop.filter(bimg_src,null);最初に挙げたのは、Kernelを構成するマトリックスの定義です。一般にfloat型が用いられ、数値の指定には、最後に「f」を付けておきます。「f」がないと、デフォルトでdouble型とみなされ、float型との矛盾が指摘されます。この例は、平滑用です。数値は、合計すると1になるようにしておかないと、変化のない部分での明るさが変わってしまいます。次は、Kernelクラスのblur(「ぼけ」の意)を構築しています。3,3はマトリックスのサイズを表し、operatorは定義済みの配列を指定しています。RenderingHints(普通はnullで良い)を指定します。周辺処理方法は、ConvolveOp.EDGE_NO_OP(周辺は処理しないで、原画像をそのままコピーする)とConvolveOp.EDGE_ZERO_FILL(周辺は強制的にゼロ(黒)にする)があります。EDGE_NO_OPは、平滑化や鮮鋭化など、変換結果が原画像に似ている場合に目立たないので、お勧めです。EDGE_ZERO_FILLは、エッジ検出など、変換結果が原画像と全く異なり、黒い部分が多くなる場合に有効です。BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);で構築しておく必要があります。誤って、BufferedImage.TYPE_INT_ARGBを用いると、透明になってしまいます。これらのクラスは「java.awt.image」に含まれており、特にクラスライブラリをインポートする必要はありません。非常に便利なAPIですが、次のような欠点もあります。従来は、原画像を拡張し、あらかじめ周辺に原画像のコピーを配して、コンボリューションによる周辺の欠落を防止できました。ConvolveOpにはその機能が含まれていないため、周辺は、処理をしないで残すEDGE_NO_OPか、周辺に強制的にゼロを書き込むEDGE_ZERO_FILLかのどちらかしかできません。平滑化と鮮鋭化はEDGE_NO_OPでごまかし、エッジ検出はEDGE_ZERO_FILLで対処するしかありません。負の演算結果が得られない。従来は、コンボリューションに使用する変数をint型で扱い、負出力も認めた上で必要に応じて絶対値を取り、0~255の範囲内に収めて画像化していました。専用APIのConvolveOpでは、出力は0~255の範囲内に収めてありますが、負出力がカットされています。したがって、負出力用に符号を反転したもう一個のオペレータを用意し、コンボリューション結果を合成する必要があります。インターフェースがBufferedImageのみである。Imageの変換が必要になります。Leedsから発表されていますが、一般的ではないので、ここでは採用しませんでした。APIの問題点を解決したコンボリューション(エッジ検出)エッジ検出に用いるオペレータは、大きな負の出力を発生することがあります。専用APIを用いない場合は、この絶対値を用いていました。専用APIのConvolveOpクラスは、負の出力はカットしてしまいますので、若干の工夫が必要です。オペレータを二個用いて、これに対処します。あるオペレータのマトリックスの各要素に-1を掛けた別のオペレータを設け、負の出力用とするのです。詳細は、図4を参照して下さい。処理全体の構成ConvolutionOpはKernelを使用し、BufferedImageを対象にコンボリューションを行います。したがって、下記の処理が必要です。画像ファイルを読み込み、Image画像を得る。メソッドreadImageFileを使用)読み込んだImage画像をBufferedImage画像に変換する。メソッドchangeToBufferedImageを使用)コンボリューションに必要なKernelオペレータ(3×3のマトリックス)を用意する。Kernelオペレータを用いて、filterメソッドでBufferedImage画像に対してコンボリューションを実行する。得られたBufferedImage画像をImage画像に変換する。メソッドchangeToImageを使用)Image画像を表示する。エッジ検出の場合(図4参照)得られた二対のBufferedImage画像を合成し、閾値THRESを与えて二個の二値Image画像を作る。メソッドcreateBrightORedBinaryImageInvertedを使用)二個の二値Image画像を合成する。メソッドcreateBlackORedBinaryImageNonInvertedを使用)合成したImage画像を表示する。図5で、左上は原画像、右上は平滑化画像、左下は鮮鋭化画像、右下はエッジ検出結果の画像です。図6は、文字や図形のエッジ検出を行った結果です。左が原画像、右がエッジ検出結果です。文字や図形のエッジ検出の結果まとめ画像の平滑化、鮮鋭化は、画像処理の中で最も一般的なもので、画像ソフトには必ず組み込まれています。APIのConvolveOpとKernelを使ってみました。意外と使い勝手が良く、お薦めできます。画像のエッジ検出は、パターン認識の前処理として使われることが多く、これも画像処理の定番ですが、上記のAPIでは不十分な点もありましたので、負出力のためのオペレータを追加し、結果を合成する方法で対処しました。APIを使用して、Java言語に全面的に書き換えたものです。版に改定)Bitmapファイルの読み書きのJava化については、多くのウェブサイト上に参考資料がありますので省略しました。APIの使用については見かけません。一般的なものとしては、以下のものがあります。NECへ入社し、NEC初のコンピュータの開発に参画。2002年定年により退職し現在に至る。C++の勉強部屋」を公開。NEW1DMM.comの施策から見る、事業をむしばむ「技術負債」への処方箋──リファクタリングの「言語化」でインシデントを予防2企業の7割超が「2025年の崖」を理解していないことが明らかに。NEW1DMM.comの施策から見る、事業をむしばむ「技術負債」への処方箋──リファクタリングの「言語化」でインシデントを予防2企業の7割超が「2025年の崖」を理解していないことが明らかに。NEW1DMM.comの施策から見る、事業をむしばむ「技術負債」への処方箋──リファクタリングの「言語化」でインシデントを予防2企業の7割超が「2025年の崖」を理解していないことが明らかに。12:00法務担当者、6割超が今後業務で「生成AIを使用したい」と回答。NEW新着記事一覧を見るイベント今後の予定を見るCodeZineは、株式会社翔泳社が運営するソフトウェア開発者向けのWebメディアです。「デベロッパーの成長と課題解決に貢献するメディア」をコンセプトに、現場で役立つ最新情報を日々お届けします。イラストの無断転載を禁じます。記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標です。