JavaCV(OpenCV)で画像変換を行いたい

## 概要
　javaで画像変換を行いたいなと思い、色々と調べていたら**JavaCV**がメジャーぽかったので、こちらを使用することにしました。**OpenCVをjava用にラッパーしたもの**の様です。OpenCVと言うとpythonのイメージしかなかったのですが、プログラミング言語は[C++](https://ja.wikipedia.org/wiki/OpenCV)で、javaでも使えるみたいですね。

## 画像のフォーマットについて
　画像のフォーマットは、**WebP**（ウェッピー）が割と新しいと言うことが分かりました。最近は、[**AVIF**](https://ics.media/entry/201001/)と言うのも出てきているみたいで、トレンドが速いなと思いましたが、まだ、OpenCVでは対応していないみたいです（多分）。「**画像の読み込み速度は、売り上げに直結している。**」みたいは記事もどこかで見かけたし、重要みたいですね。

[アマゾンのページ表示速度を劇的に改善した6つの実践テクニック【SEO情報まとめ】](https://webtan.impress.co.jp/e/2022/02/04/42291)


## その他のライブラリ

### image-io
 WebPの変換ライブラリとして、[**image-io**](https://qiita.com/chenglin/items/61472832fd26ab257a2f)と言うものがあり、使い方も簡単でした。**自動変換**と**マニュアル変換**の2つがあり、マニュアルでやると逆に容量が増えたので、設定は細かくやる必要がありそうです（詳しくは調べておりません）。

git
[webp-imageio](https://github.com/sejda-pdf/webp-imageio)

### OpenCV.js
　一応、javascript版の[**OpenCV.js**](https://docs.opencv.org/3.4/d5/d10/tutorial_js_root.html)と言うのもあるらしいです。ですが、これは機能が限定されているみたいで、画像のフォーマット変換には対応していないみたいでした（node.jsなら出来るみたいです）。


## 画像変換の際の注意点
　あまり詳しくないので違っていたらゴメンナサイ。画像のフォーマットを変換する際の注意点として、**jpg**などの非可逆圧縮のフォーマットは品質が保証できないかもしれません。処理的には、**画像の再圧縮**と言うことになるのかなと思いますが、**png**や**tiff**と言った可逆圧縮のフォーマットであれば、問題ないかと思います。~~と言うか、書いててわざわざ変換までする必要はあるのかなという気もしてきた。~~
　・png, tiff -> webp : OK
　・jpb -> webP : NG？


## JavaCVかOpenCVか
　Javaの場合だと、[**JavaCV**](https://mvnrepository.com/artifact/org.bytedeco/javacv)と[**OpenCV**](https://mvnrepository.com/search?q=opencv&sort=relevance)の2つの選択肢がありますが、**maven**で見てみると、OpenCVは殆ど更新されていないみたいなので、JavaCVを使用して問題ないかと思います。


## 手動で設定する方法（eclipse）
　eclipseで手動で設定する場合は、[こちら](https://docs.opencv.org/4.x/d1/d0a/tutorial_java_eclipse.html)の通りに設定すれば問題ないかと思います（動作確認済み）。一応、**maven**の方が簡単なので、今回はmavenで設定しようと思います。

## mavenで設定する方法
　サイトで色々と書かれていますが、取り合えず、[こちら](https://github.com/bytedeco/javacv)の通りにすれば問題ない様です。標準的な使用であれば、設定するのは**下記のみ**です。（昔の記事だと、javaCPPも記述しないといけないとか色々書かれていて、かなり振り回されましたが（笑）、公式サイトの通りにするのが良いようです）

```pom.xml
  <dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv-platform</artifactId>
    <version>1.5.7</version>
  </dependency>
```
　
## サンプルコード

こちらも、[公式サイト](https://docs.opencv.org/4.x/d1/d0a/tutorial_java_eclipse.html)通りに記述すれば問題ない様です。

```sample.java
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.*;

public class Smoother {
    public static void smooth(String filename) {
        Mat image = imread(filename);
        if (image != null) {
            GaussianBlur(image, image, new Size(3, 3), 0);
            imwrite(filename, image);
        }
    }
}
```

## コードを書く時の注意点（重要）

かなりハマったので、記述しておきます。下記の様に書くとエラーになります。

```sample.java
    //画像読み込み
    Mat image = Imgcodecs.imread(filename);  //Imgcodecs.追記
```

**Imgcodecs**は**imread**のクラスですが、上記の様にImgcodecsを指定すると、JavaCVを通してでなく、**OpenCVを直接呼び出す**ことになり、エラーとなります。公式サイトのサンプル通りに**メソッドのみ**を書いて下さい。下記の様に**OpenCVのクラスが自動的にimport**されます。

```import.java
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Size;
import org.opencv.imgcodecs.Imgcodecs;  //エラーの原因(JavaCVとOpenCVが混在している）
import org.opencv.imgproc.Imgproc;      //エラーの原因(JavaCVとOpenCVが混在している）
```
ですが、**手動でJavaCVを設定した場合は、上記の様に書いても問題なく動作しました。** （何でかな？OpenCVで書いている状態だったのかな？）取り合えず、JavaCVとOpenCVをごちゃ混ぜで書くと混乱するので、**JavaCVに統一して書く**方が良いかと思います。

※因みにですが、JavaCVとOpenCVでは、メソッド名は同じでも引数の型が違うなど、若干の違いがあるようです。