- 投稿日:2019-05-21T22:35:20+09:00
JUnitでモックを利用したテストコード(EasyMock中心)
JUnitでモックを使ったテストについてです。
職場でテストコードを普及させるための記事2回目になります。
EasyMockについてが中心となるので、あまり最近の話ではありません。実行環境
- Java 1.8
- JUnit 4.4
- EasyMock 2.4
- Seasar 2.4.46
モックとは
モックオブジェクト(Mock Object)とは、ソフトウェアテスト時、特にテスト駆動開発、ビヘイビア駆動開発における代用の下位モジュールスタブの一種。スタブと比較して、検査対象のモジュール
がその下位モジュールを正しく利用しているかどうかを検証するのに使われる。モックオブジェクト 出典: フリー百科事典『ウィキペディア(Wikipedia)』
使い方としては、例えば以下のようにHelloJunitというクラスを作成しているとします。
このクラスをテストしようとした際に、もしGreetDaoクラスができていない(あとはDaoで参照しているDBが用意されていないとか)とした場合に、普通にテストしてしまうとエラーになってしまうと思います。HelloJunitpublic class HelloJunit { @Binding GreetDao greetDao; public String sayGreeting() { return greetDao.getGreet(); }本来はHelloJunitクラスをテストしたいだけなので、依存先(GreetDao)のコードができていなくてもテストできるべきだよねということで、ひとまず動くようにハリボテのクラスを用意して動かせるようにしようよ。というのがモックの役割になります。
どうやってモックを作るのか
以下のような方法があります。
- モックライブラリを利用
- モックを作成したいクラスを継承してテスト用に作成する
モックライブラリとしては、
Mockito
、JMockit
、そしてEasyMock
、MockInterceptor
などがあります。最近では
Mockito
がよく使われている印象です。Seasar2では
EasyMock
、MockInterceptor
がデフォルトで入っています。
いまだにSeasar2を利用しているような環境で新しいライブラリを入れるのは難しいと思いますので、今回はEasyMockで進めたいと思います。EasyMockを利用したテストコードサンプル
とりあえずコード
プロダクトコードについて上で紹介した内容から少し変更しています。
理由については後ほど説明します。プロダクトコードpublic class HelloJunit { GreetDao greetDao; public HelloJunit(GreetDao greetDao) { this.greetDao = greetDao; } public String sayGreeting() { return greetDao.getGreet(); } }テストコードはこちらです。
テストコードimport static org.easymock.EasyMock.*; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; import org.seasar.framework.unit.annotation.EasyMock; import org.seasar.sastruts.example.dao.GreetDao; public class HelloJunitTest { HelloJunit helloJunit; @EasyMock GreetDao greetDao; @Before public void setUp() { greetDao = createMock(GreetDao.class); helloJunit = new HelloJunit(greetDao); } @Test public void 挨拶を言う() throws Exception { // setup(事前準備) expect(greetDao.getGreet()).andReturn("Hello"); replay(greetDao); // exercise(実行) String actual = helloJunit.sayGreeting(); // verify(検証) String expected = "Hello"; assertThat(actual, is(expected)); verify(greetDao); // tear down(後処理) // 何かあれば・・・ } }なんとなくわかると思いますが解説します。
EasyMockアノテーション
メンバー変数にGreetDaoを用意しているのですが、
EasyMockアノテーション
がついています。
これをつけることでEasyMockを利用可能になります。createMock
setUpメソッドでは
createMock
メソッドを利用して、greetDaoを作成しています。
ここで作成したgreetDaoをテスト対象メソッドであるhelloJunitのインスタンス生成時に渡してあげることで、モックがセットされることになります。テストメソッド内のsetup
setup(事前準備)というコメントの中では、
expect
メソッドを利用しています。
ここがモックの挙動を決める一番重要な部分です。greetDao.getGreet()がこういう呼び出し方をされた場合、〜を返すよというのを設定しています。
expected()
でメソッドの呼び出し方を指定。その後のandReturn()
で戻り値を設定します。
今回の場合は、引数なしのgreetDao.getGreet()を呼び出した場合に、"Hello"を返すという設定をしています。
replay
というメソッドは直前で設定したモックの挙動を記憶するというイメージです。
expected()を実行したらreplayをするというようにしてください。exercise
ここではテストをしたいメソッドを実行して、変数に格納しています。
格納する変数はどのような型であってもactual
に統一するとわかりやすいと言われています。verify
ここでは、
helloJunit.sayGreeting();
の戻り値と期待値を比較しています。
また、verify(greetDao);
というのは、setup内で指定したモックの挙動が想定通り呼び出されたかを検証します。
もしhelloJunit.sayGreeting();
が1回も呼び出されていなければエラーが返却されます。tear down
ここはテスト後の後処理を行います。
例えばテストデータをDBに投入していたとした場合、そのデータを削除したりを行います。EasyMockの利用方法
引数をチェックする
今回はgreetDaoのfindGreetメソッドが想定通りの呼び出され方をしているか確認します。
テスト対象コードpublic String sayGreeting() { return greetDao.findGreet(1); }
expect()
内に期待しているメソッドの呼び出し方をそのまま書きます。
今回の場合は、findGreet
の引数に1が入ることを想定しているので、そのままfindGreet(1)
を記載します。テストコード@Test public void 引数テスト() throws Exception { // setup(事前準備) expect(greetDao.findGreet(1)).andReturn("Hello"); replay(greetDao); // exercise(実行) String actual = helloJunit.sayGreeting(); // verify(検証) verify(greetDao); }ちなみに、もし
findGreet(2);
で呼び出されていた場合には以下のようなエラーが出力されます。エラーの場合の参考java.lang.AssertionError: Unexpected method call findGreet(2): findGreet(1): expected: 1, actual: 0 at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:32) at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:61) at com.sun.proxy.$Proxy4.findGreet(Unknown Source) at org.seasar.sastruts.example.service.HelloJunit.sayGreeting(HelloJunit.java:17) at org.seasar.sastruts.example.service.HelloJunitTest.引数テスト(HelloJunitTest.java:52) --以降略--戻り値をセットして後続処理をテストする
findGreet
の戻り値によって分岐を入れてみました。
今回のテストでは、パスタが返却されるパターンをテストしたいと思います。プロダクションコードpublic String sayGreeting() { String greet = greetDao.findGreet(1); if (greet.contentEquals("Hello")) { return "パスタ"; } else { return "ラーメン"; } }戻り値を設定するには、
andReturn
に戻り値を指定します。
今回の場合は、"Hello"が返却されるようになります。テストコード@Test public void 引数テスト() throws Exception { // setup(事前準備) expect(greetDao.findGreet(1)).andReturn("Hello"); replay(greetDao); // exercise(実行) String actual = helloJunit.sayGreeting(); // verify(検証) String expected = "パスタ"; assertThat(actual, is(expected)); verify(greetDao); }戻り値をセットして後続処理をテストする
void型のメソッドをテストする方法です。
プロダクションコード(GreetDao)public interface GreetDao { public void insertGreet(String greet); }プロダクションコード(HelloJunit)public String addGreet() { greetDao.insertGreet("Good Night"); return "OK"; }void型をテストする場合は、テストコードの中で実際にvoidメソッドを実行します。
その後にexpectLastCall()
を呼び出します。
これによって、直前のメソッド実行を記憶して検証することができます。ちなみに同一のvoidメソッドを二回実行している場合には、
expectLastCall().times(2);
というようにtimes()を付与することで、回数分実行されたかを検証します。テストコード@Test public void voidメソッドをテスト() throws Exception { // setup(事前準備) greetDao.insertGreet("Good Night"); expectLastCall(); replay(greetDao); // exercise(実行) String actual = helloJunit.sayGreeting(); // verify(検証) verify(greetDao); }EasyMockの注意点
EasyMockでは、インターフェースのクラスしかモックすることができません。
もし具象クラスをモックしたい場合は、次に紹介する継承する方法を試してください。補足:
org.easymock.classextension.EasyMock
を利用することで具象クラスもテスト可能ですが、古いバージョンのSeasarを利用している場合は入っていない可能性あります。継承してチェックする
テスト対象のメソッド内で利用しているクラスがインターフェースでなかったり、テストするには不都合があるような場合には、テストのために継承してモッククラスを自分で用意することもあります。
例えば、メソッドで返却されるBeanにequalsメソッドがオーバーライドされておらず、一つ一つのフィールドをチェックするのがめんどくさいような場合は、以下のようにequalsを継承してテストします。
テスト対象のプロダクションコードpublic TransferResultDto transfer(String payerAccountId, String payeeAccountId, String payerName, long transferAmount) { Balance payerBalance = balanceDao.findByAccountId(payerAccountId); if (payerBalance == null) throw new BusinessLogicException("残高が取得できません"); if (transferAmount > payerBalance.amount) throw new BusinessLogicException("残高が足りません"); Balance payeeBalance = balanceDao.findByAccountId(payeeAccountId); if (payeeBalance == null) throw new BusinessLogicException("振込先口座が存在しません"); LocalDateTime transferDate = LocalDateTime.now(); Transfer peyerTransaction = new Transfer(); peyerTransaction.accountId = payerAccountId; peyerTransaction.name = payerBalance.name; peyerTransaction.transferAmount = -transferAmount; peyerTransaction.transferDate = transferDate; Transfer payeeTransaction = new Transfer(); payeeTransaction.accountId = payeeAccountId; payeeTransaction.name = payeeBalance.name; payeeTransaction.transferAmount = transferAmount; payeeTransaction.transferDate = transferDate; transferDao.insertTransfer(peyerTransaction); transferDao.insertTransfer(payeeTransaction); balanceDao.updateAmount(payerAccountId, -transferAmount); balanceDao.updateAmount(payeeAccountId, transferAmount); Balance updatedPayerBalance = balanceDao.findByAccountId(payerAccountId); return new TransferResultDto(payerAccountId, payeeAccountId, payerBalance.name, payeeBalance.name, transferAmount, updatedPayerBalance.amount); } }戻り値のBeanpublic class TransferResultDto { private final String payerAccountId; private final String payeeAccountId; private final String payerName; private final String payeeName; private final long transferAmount; private final long amount; public TransferResultDto(String payerAccountId, String payeeAccountId, String payerName, String payeeName, long transferAmount, long amount) { this.payerAccountId = payerAccountId; this.payeeAccountId = payeeAccountId; this.payerName = payerName; this.payeeName = payeeName; this.transferAmount = transferAmount; this.amount = amount; } public String getPayerAccountId() { return payerAccountId; } public String getPayeeAccountId() { return payeeAccountId; } public String getPayerName() { return payerName; } public String getPayeeName() { return payeeName; } public long getTransferAmount() { return transferAmount; } public long getAmount() { return amount; } }これをテストする場合には、テストクラス内で
TransferResultDto
を継承してTransferResultDtoMock
クラスを作成します。
このTransferResultDtoMock
クラスの中で全てのフィールドを比較するequalsメソッドを用意して、テストする際にはassertThat(actual, is(expected));
というように isで比較できるようになります。今回は、equalsメソッドを書くのがめんどくさいので、lombokを利用して自動生成しました
public class TransferServiceTest { @Test public void 継承モックを試す() { // setup TransferResultDtoMock expected = new TransferResultDtoMock("1", "2", ACCOUNT1_BEFORE_BALANCE.name, ACCOUNT2_BALANCE.name, 2000, ACCOUNT1_AFTER_BALANCE.amount); TransferResultDto transferResultDto = transferService.transfer("1", "2", "田中太郎", 1000); TransferResultDtoMock actual = new TransferResultDtoMock(transferResultDto); assertThat(actual, is(expected)); } @EqualsAndHashCode(callSuper = true) private class TransferResultDtoMock extends TransferResultDto { public TransferResultDtoMock(String payerAccountId, String payeeAccountId, String payerName, String payeeName, long transferAmount, long amount) { super(payerAccountId, payeeAccountId, payerName, payeeName, transferAmount, amount); } public TransferResultDtoMock(TransferResultDto transferResultDto) { super(transferResultDto.getPayerAccountId(), transferResultDto.getPayeeAccountId(), transferResultDto.getPayerName(), transferResultDto.getPayeeName(), transferResultDto.getTransferAmount(), transferResultDto.getAmount()); } } }テストコードを書くにあたって意識すべきこと
ビジネスロジックに関する部分は独立した実装にする
最初にHelloJunit内でGreetDaoをDIするロジックを、アノテーションからコンストラクタ型に変更したと思います。
その理由としては、アノテーションで表現する場合、HelloJunitがフレームワーク(Seasar2)に依存する形になってしまうからです。プロダクトコードpublic class HelloJunit { GreetDao greetDao; public HelloJunit(GreetDao greetDao) { this.greetDao = greetDao; } public String sayGreeting() { return greetDao.getGreet(); } }例えば今後Springに移行することになった場合、アノテーションでDIする場合は @ Autowiredを利用することになります。
なので、コンストラクタでDIすることでフレームワークへの変更も用意になります。また、テストコードという観点からもアノテーションで実現している場合には、クラスの宣言時に
@RunWith(Seasar2.class)
を指定する必要がありますが、コンストラクタでDIしている場合には、new してあげればテストが簡単にできます。参考記事
テストが書きやすいコードを書く
テストを行うにあたり、テストが書きやすいコードというのは重要になります。
例えば以下のようなコードは、
TimeJunit.getTime()
staticメソッドの結果に応じて条件分岐をしているのですが、staticメソッドはモックで置き換えることが難しいです。staticメソッドを利用しているpublic class ExampleJunit { public String sayGreeting() { int term = TimeJunit.getTime(); switch(term) { case 1: return "パスタ"; case 2: return "ラーメン"; default: return "ご飯"; } } }あとは継承していてスーパークラスのメソッドを利用している場合もテストしにくいコードになります。
例えば古いシステムだとよく使われているようなこんなロジック。スーパークラスpublic abstract class AbstractJunit { public String sayGreeting() { return this.getMessage(); } abstract protected String getMessage(); }継承クラスpublic class ExampleJunit extends AbstractJunit { protected String getMessage() { int term = 1; switch(term) { case 1: return "パスタ"; case 2: return "ラーメン"; default: return "ご飯"; } } }今回の例であればテスト可能ですが、実際に業務で継承を利用しているようなケースだと、スーパークラスが神様クラス(なんでもロジックを入れる便利クラス)になっていて、スパゲッティソースになっていたりするので、テストでリフレクションとかしなきゃいけなくなってしまうので扱い辛いです。
本当に継承を使うべきか考えて実装しましょう。
参考記事
その他参考
- 投稿日:2019-05-21T20:56:26+09:00
Javaのバージョン確認
・インストールしたJavaのバージョンを確認をしたい時
windowsの場合
コマンドプロンプトを開く
macの場合
ターミナルを開く「java -version」のコマンドをコピーして貼り付け。
下のように表示されます。java version "1.8.0_131" Java(TM) SE Runtime Environment (build 1.8.0_131-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)・確認方法
「java version」の直後のダブルクォートで囲まれた部分(1.8.0_131)がバージョンです。
「Java HotSpot(TM) 64-Bit」が64ビット版。64ではない場合は32ビット版です。記事の掲載理由
環境構築の際に、既にインストールされているJavaが64bitなのか32bitなのか気になったため記載しました。
- 投稿日:2019-05-21T18:21:31+09:00
Desktop : OpenCV Mean Filter
Goal
Test OpenCV Mean filter.
OpenCV_MeanFilter.javaimport org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; public class OpenCV_MeanFilter { static{System.loadLibrary(Core.NATIVE_LIBRARY_NAME);} private JFrame frmjavaSwing; /** * Launch the application. */ public static void main(String[] args){ EventQueue.invokeLater(new Runnable() { public void run() { try { OpenCV_MeanFilter window = new OpenCV_MeanFilter(); window.frmjavaSwing.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the application. */ public OpenCV_MeanFilter() { initialize(); } /** * Initialize the contents of the frame. */ private void initialize(){ final Mat source = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\baboon.jpg"); BufferedImage image=matToBufferedImage(source); frmjavaSwing = new JFrame(); frmjavaSwing.setTitle("opencv 均值濾波器練習"); frmjavaSwing.setBounds(100, 100, 560, 620); frmjavaSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmjavaSwing.getContentPane().setLayout(null); final JLabel lblNewLabel = new JLabel(""); lblNewLabel.setBounds(5, 60, image.getHeight()+10, image.getWidth()+10); lblNewLabel.setIcon(new ImageIcon(image)); frmjavaSwing.getContentPane().add(lblNewLabel); JButton btn3 = new JButton("Kernel-Size3"); btn3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(Convolution(source,3)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btn3.setBounds(10, 10, 114, 23); frmjavaSwing.getContentPane().add(btn3); JButton btnNewButton = new JButton("Kernel-Size7"); btnNewButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(Convolution(source,7)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btnNewButton.setBounds(162, 10, 114, 23); frmjavaSwing.getContentPane().add(btnNewButton); JButton btn9 = new JButton("Kernel-Size9"); btn9.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(Convolution(source,9)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btn9.setBounds(316, 10, 114, 23); frmjavaSwing.getContentPane().add(btn9); } public Mat Convolution(Mat source,int kernelSize){ Mat kernel = Mat.ones(kernelSize,kernelSize, CvType.CV_32F); for(int i=0; i<kernel.rows(); i++){ for(int j=0; j<kernel.cols(); j++){ double[] tmp = kernel.get(i, j); tmp[0]=tmp[0]/(kernelSize * kernelSize); kernel.put(i,j, tmp); } } Mat destination=new Mat(source.rows(),source.cols(),source.type()); Imgproc.filter2D(source, destination, -1, kernel); return destination; } public BufferedImage matToBufferedImage(Mat matrix) { int cols = matrix.cols(); int rows = matrix.rows(); int elemSize = (int)matrix.elemSize(); byte[] data = new byte[cols * rows * elemSize]; int type; matrix.get(0, 0, data); switch (matrix.channels()) { case 1: type = BufferedImage.TYPE_BYTE_GRAY; break; case 3: type = BufferedImage.TYPE_3BYTE_BGR; // bgr to rgb byte b; for(int i=0; i<data.length; i=i+3) { b = data[i]; data[i] = data[i+2]; data[i+2] = b; } break; default: return null; } BufferedImage image2 = new BufferedImage(cols, rows, type); image2.getRaster().setDataElements(0, 0, cols, rows, data); return image2; } }Result
- 投稿日:2019-05-21T16:54:17+09:00
Desktop : OpenCV Merge Two Images In Any Shape
Goal
Test OpenCV merge two image with ROI.
OpenCV_MergeTwoImgAnyShape.javaimport org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.Rect; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import java.util.ArrayList; import java.util.List; public class OpenCV_MergeTwoImgAnyShape { public static void main( String[] args ) { try{ System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); //大圖(母圖) Mat source = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\ncku.jpg",Imgcodecs.CV_LOAD_IMAGE_COLOR); //小圖(子圖) Mat source1 = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\jelly_studio_logo.jpg",Imgcodecs.CV_LOAD_IMAGE_COLOR); Mat destination=source.clone(); // to make the white region transparent Mat mask2=new Mat(); Mat dst=new Mat(); Imgproc.cvtColor(source1,mask2,Imgproc.COLOR_BGR2GRAY); Imgproc.threshold(mask2,mask2,230,255, Imgproc.THRESH_BINARY_INV); List<Mat> planes = new ArrayList<Mat>() ; List<Mat> result = new ArrayList<Mat>() ; Mat result1=new Mat(); Mat result2=new Mat(); Mat result3=new Mat(); Core.split(source1, planes); Core.bitwise_and(planes.get(0), mask2, result1); Core.bitwise_and(planes.get(1), mask2, result2); Core.bitwise_and(planes.get(2), mask2, result3); result.add(result1); result.add(result2); result.add(result3); Core.merge(result, dst); //以上白色變透明 //再把小圖copy到大圖 Rect roi=new Rect(50,50,90,62);//不能比原圖大,及小 Mat destinationROI = source.submat( roi ); dst.copyTo( destinationROI , dst); Imgcodecs.imwrite("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\merge3.jpg", source); }catch (Exception e) { System.out.println("error: " + e.getMessage()); } } }Result
- 投稿日:2019-05-21T16:43:50+09:00
Desktop : OpenCV Merge Two Image
Goal
Test OpenCV to merge two images.
OpenCV_MergeTwoImage.javaimport org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.Rect; import org.opencv.imgcodecs.Imgcodecs; public class OpenCV_MergeTwoImage { public static void main( String[] args ) { try{ System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\ncku.jpg",Imgcodecs.CV_LOAD_IMAGE_COLOR); Mat source1 = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\jelly_studio_logo.jpg",Imgcodecs.CV_LOAD_IMAGE_COLOR); Mat destination=source.clone(); //Imgproc.resize Rect roi=new Rect(50,50,90,62); Mat destinationROI = source.submat( roi ); source1.copyTo( destinationROI , source1); Imgcodecs.imwrite("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\merge2.jpg", source); }catch (Exception e) { System.out.println("error: " + e.getMessage()); } } }Result
- 投稿日:2019-05-21T16:32:22+09:00
Desktop : OpenCV Add Broad
Goal
Test OpenCV add broad around a image.
OpenCV_AddBoard.javaimport org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.imgcodecs.Imgcodecs; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.image.BufferedImage; public class OpenCV_AddBoard { static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);} private JFrame frmjavaSwing; /** * Launch the application. */ public static void main(String[] args){ EventQueue.invokeLater(new Runnable() { public void run() { try { OpenCV_AddBoard window = new OpenCV_AddBoard(); window.frmjavaSwing.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the application. */ public OpenCV_AddBoard() { initialize(); System.out.println("Core.BORDER_CONSTANT="+Core.BORDER_CONSTANT); System.out.println("Core.BORDER_REPLICATE="+Core.BORDER_REPLICATE); System.out.println("Core.BORDER_TRANSPARENT="+Core.BORDER_TRANSPARENT); System.out.println("Core.BORDER_WRAP="+Core.BORDER_WRAP); System.out.println("Core.BORDER_DEFAULT="+Core.BORDER_DEFAULT); System.out.println("Core.BORDER_ISOLATED="+Core.BORDER_ISOLATED); System.out.println("Core.BORDER_REFLECT="+Core.BORDER_REFLECT); System.out.println("Core.BORDER_REFLECT101="+Core.BORDER_REFLECT101); System.out.println("Core.BORDER_REFLECT_101="+Core.BORDER_REFLECT_101); } /** * Initialize the contents of the frame. */ private void initialize() { frmjavaSwing = new JFrame(); frmjavaSwing.setTitle("讀取影像至Java Swing視窗"); frmjavaSwing.setBounds(100, 100, 613, 690); frmjavaSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmjavaSwing.getContentPane().setLayout(null); final JLabel showAlphaValue = new JLabel("0"); showAlphaValue.setBounds(306, 10, 46, 15); frmjavaSwing.getContentPane().add(showAlphaValue); final JLabel showBetaValue = new JLabel("0"); showBetaValue.setBounds(306, 43, 46, 15); frmjavaSwing.getContentPane().add(showBetaValue); final JLabel lblNewLabel = new JLabel(""); lblNewLabel.setBounds(10, 68, 585, 578); frmjavaSwing.getContentPane().add(lblNewLabel); final JSlider slider_beta = new JSlider(); slider_beta.setValue(0); slider_beta.setMaximum(4); slider_beta.setBounds(106, 36, 200, 25); frmjavaSwing.getContentPane().add(slider_beta); final JSlider slider_alpha = new JSlider(); slider_alpha.setMaximum(5); slider_alpha.setValue(0); slider_alpha.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { //System.out.println(slider_alpha.getValue()); showAlphaValue.setText((float)slider_alpha.getValue()/100+""); BufferedImage newImage=matToBufferedImage(AddBoard((float)slider_alpha.getValue()/100,slider_beta.getValue())); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); slider_alpha.setBounds(96, 10, 200, 25); frmjavaSwing.getContentPane().add(slider_alpha); JLabel lblAlpha = new JLabel("邊框大小"); lblAlpha.setBounds(10, 20, 76, 15); frmjavaSwing.getContentPane().add(lblAlpha); JLabel lblBeta = new JLabel("邊框型式"); lblBeta.setBounds(10, 45, 62, 15); frmjavaSwing.getContentPane().add(lblBeta); slider_beta.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { showBetaValue.setText((float)slider_beta.getValue()+""); BufferedImage newImage=matToBufferedImage(AddBoard((float)slider_alpha.getValue()/100,slider_beta.getValue())); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); } public Mat AddBoard(float borderSize,int borderType){ Mat source = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\clean.jpg"); Mat destination=new Mat(source.rows(),source.cols(),source.type()); float top; float bottom; float left; float right; top=((borderSize*source.rows())); bottom=(borderSize*source.rows()); left=(borderSize*source.cols()); right=(borderSize*source.cols()); destination=source; Core.copyMakeBorder(source, destination, (int)top, (int)bottom, (int)left, (int)right, borderType); return destination; } public BufferedImage matToBufferedImage(Mat matrix) { int cols = matrix.cols(); int rows = matrix.rows(); int elemSize = (int)matrix.elemSize(); byte[] data = new byte[cols * rows * elemSize]; int type; matrix.get(0, 0, data); switch (matrix.channels()) { case 1: type = BufferedImage.TYPE_BYTE_GRAY; break; case 3: type = BufferedImage.TYPE_3BYTE_BGR; // bgr to rgb byte b; for(int i=0; i<data.length; i=i+3) { b = data[i]; data[i] = data[i+2]; data[i+2] = b; } break; default: return null; } BufferedImage image2 = new BufferedImage(cols, rows, type); image2.getRaster().setDataElements(0, 0, cols, rows, data); return image2; } }Result
- 投稿日:2019-05-21T16:02:56+09:00
Desktop : OpenCV OpenCV_SalonUseBlurAddWeighted
Goal
Use OpenCV make salon filter.
OpenCV_SalonUseBlurAddWeighted.javaimport org.omg.CORBA.FREE_MEM; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.Size; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.image.BufferedImage; import java.nio.Buffer; public class OpenCV_SalonUseBlurAddWeighted { static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME);} private JFrame frmjavaSwing; /** * Launch the application. */ public static void main(String[] args){ EventQueue.invokeLater(new Runnable() { @Override public void run() { try{ OpenCV_SalonUseBlurAddWeighted window = new OpenCV_SalonUseBlurAddWeighted(); window.frmjavaSwing.setVisible(true); }catch (Exception e){ e.printStackTrace(); } } }); } /** * Create the application. */ public OpenCV_SalonUseBlurAddWeighted(){ initialize(); } /** * Initialize the contents of the frame. */ private void initialize() { final Mat source1 = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\clean.jpg"); final Mat source2 = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\clean.jpg"); BufferedImage image=matToBufferedImage(BlurAndmerge(source1,source2,1,1,1,1)); frmjavaSwing = new JFrame(); frmjavaSwing.setTitle("opencv 夢幻沙龍處理練習"); frmjavaSwing.setBounds(100, 100, 520, 550); frmjavaSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmjavaSwing.getContentPane().setLayout(null); final JLabel showAlphaValue = new JLabel("0"); showAlphaValue.setBounds(260, 10, 29, 15); frmjavaSwing.getContentPane().add(showAlphaValue); final JLabel showBetaValue = new JLabel("0"); showBetaValue.setBounds(259, 35, 29, 15); frmjavaSwing.getContentPane().add(showBetaValue); final JLabel lblNewLabel = new JLabel(""); lblNewLabel.setBounds(10, 68, 438, 438); lblNewLabel.setIcon(new ImageIcon(image)); frmjavaSwing.getContentPane().add(lblNewLabel); final JSlider slider_Blur = new JSlider(); slider_Blur.setValue(0); slider_Blur.setMaximum(101); slider_Blur.setBounds(57, 35, 200, 25); frmjavaSwing.getContentPane().add(slider_Blur); final JSlider slider_Gamma = new JSlider(); slider_Gamma.setMaximum(200); slider_Gamma.setValue(0); slider_Gamma.setBounds(290, 35, 115, 25); frmjavaSwing.getContentPane().add(slider_Gamma); final JSlider slider_Alpha = new JSlider(); slider_Alpha.setMaximum(20); slider_Alpha.setValue(0); slider_Alpha.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { //System.out.println(slider_Alpha.getValue()/10); showAlphaValue.setText((float)slider_Alpha.getValue()/10+""); if(slider_Blur.getValue()%2==0){ slider_Blur.setValue(slider_Blur.getValue()+1); } BufferedImage newImage=matToBufferedImage(BlurAndmerge(source1,source2,(float)slider_Alpha.getValue()/10,1,-slider_Gamma.getValue(),slider_Blur.getValue())); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); slider_Alpha.setBounds(57, 10, 200, 25); frmjavaSwing.getContentPane().add(slider_Alpha); JLabel lblAlpha = new JLabel("透明度"); lblAlpha.setBounds(10, 20, 46, 15); frmjavaSwing.getContentPane().add(lblAlpha); JLabel lblBetaval = new JLabel("模糊度"); lblBetaval.setBounds(10, 45, 46, 15); frmjavaSwing.getContentPane().add(lblBetaval); JLabel lblGamma = new JLabel("明亮度"); lblGamma.setBounds(290, 10, 46, 15); frmjavaSwing.getContentPane().add(lblGamma); final JLabel showTypeValue = new JLabel("0"); showTypeValue.setBounds(415, 35, 36, 15); frmjavaSwing.getContentPane().add(showTypeValue); slider_Gamma.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { showTypeValue.setText(slider_Gamma.getValue()+""); BufferedImage newImage=matToBufferedImage(BlurAndmerge(source1,source2,(float)slider_Alpha.getValue()/10,1,-slider_Gamma.getValue(),slider_Blur.getValue())); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); slider_Blur.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { if(slider_Blur.getValue()%2==0){ slider_Blur.setValue(slider_Blur.getValue()+1); } showBetaValue.setText(slider_Blur.getValue()+""); BufferedImage newImage=matToBufferedImage(BlurAndmerge(source1,source2,(float)slider_Alpha.getValue()/10,1,-slider_Gamma.getValue(),slider_Blur.getValue())); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); } public Mat BlurAndmerge(Mat source1,Mat source2,double alpha,double beta,double gamma,int GaussianKernelSize){ Mat processBlur=new Mat(source1.rows(),source1.cols(),source1.type()); Mat destination=new Mat(source1.rows(),source1.cols(),source1.type()); Imgproc.GaussianBlur(source1, processBlur,new Size(GaussianKernelSize,GaussianKernelSize),0,0); Core.addWeighted(processBlur, alpha, source2, beta, gamma, destination); return destination; } public BufferedImage matToBufferedImage(Mat matrix) { int cols = matrix.cols(); int rows = matrix.rows(); int elemSize = (int)matrix.elemSize(); byte[] data = new byte[cols * rows * elemSize]; int type; matrix.get(0, 0, data); switch (matrix.channels()) { case 1: type = BufferedImage.TYPE_BYTE_GRAY; break; case 3: type = BufferedImage.TYPE_3BYTE_BGR; // bgr to rgb byte b; for(int i=0; i<data.length; i=i+3) { b = data[i]; data[i] = data[i+2]; data[i+2] = b; } break; default: return null; } BufferedImage image2 = new BufferedImage(cols, rows, type); image2.getRaster().setDataElements(0, 0, cols, rows, data); return image2; } }Result
- 投稿日:2019-05-21T16:01:52+09:00
Desktop : OpenCV Mosaic
Goal
Make a mosaic image with OpenCV.
OpenCV_Mosaic.javaimport org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.Size; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import java.util.ArrayList; import java.util.List; public class OpenCV_Mosaic { public static void main(String[] args){ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); Mat im = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\clean.jpg"); Imgproc.resize(im,im,new Size(),0.1,0.1,Imgproc.INTER_NEAREST); Imgproc.resize(im,im,new Size(),10.0,10.0,Imgproc.INTER_NEAREST); Imgcodecs.imwrite("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\clean_mosaic.jpg", im); } }Result
- 投稿日:2019-05-21T15:48:43+09:00
Desktop : OpenCV Concat
Gaol
Test OpenCV concat.
OpenCV_Concat.javaimport org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.imgcodecs.Imgcodecs; import java.util.ArrayList; import java.util.List; public class OpenCV_Concat { public static void main(String[] args){ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); Mat im = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\ncku.jpg"); List<Mat> matList=new ArrayList<Mat>(); Mat hdst=new Mat(); Mat vdst=new Mat(); //3¦¸ matList.add(im); matList.add(im); matList.add(im); Core.hconcat(matList, hdst); Core.vconcat(matList, vdst); Imgcodecs.imwrite("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\hconcat_ncku.jpg",hdst); Imgcodecs.imwrite("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\vconcat_ncku.jpg",vdst); } }Result
- 投稿日:2019-05-21T14:56:15+09:00
Desktop : OpenCV color space
Goal
Test OpenCV change color space.
OpenCV_ChangeColorSpace.javaimport org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; public class OpenCV_ChangeColorSpace { static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);} private JFrame frmjavaSwing; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { OpenCV_ChangeColorSpace window = new OpenCV_ChangeColorSpace(); window.frmjavaSwing.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the application. */ public OpenCV_ChangeColorSpace() { initialize(); } /** * Initialize the contents of the frame. */ private void initialize() { final Mat source = Imgcodecs.imread( "D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\clean.jpg"); BufferedImage image=matToBufferedImage(source); frmjavaSwing = new JFrame(); frmjavaSwing.setTitle("opencv 顏色空間轉換練習"); frmjavaSwing.setBounds(100, 100, 560, 620); frmjavaSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmjavaSwing.getContentPane().setLayout(null); final JLabel lblNewLabel = new JLabel(""); lblNewLabel.setBounds(5, 60, image.getHeight()+10, image.getWidth()+10); lblNewLabel.setIcon(new ImageIcon(image)); frmjavaSwing.getContentPane().add(lblNewLabel); JButton btnRK0 = new JButton("RGB2HLS"); btnRK0.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(colorSpaceConversion(source,0)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btnRK0.setBounds(5, 10, 110, 23); frmjavaSwing.getContentPane().add(btnRK0); JButton btnK1 = new JButton("RGB2BGR"); btnK1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(colorSpaceConversion(source,1)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btnK1.setBounds(5, 43, 110, 23); frmjavaSwing.getContentPane().add(btnK1); JButton btnK2 = new JButton("RGB2HSV"); btnK2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(colorSpaceConversion(source,2)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btnK2.setBounds(118, 10, 98, 23); frmjavaSwing.getContentPane().add(btnK2); JButton btnK3 = new JButton("RGB2Lab"); btnK3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(colorSpaceConversion(source,3)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btnK3.setBounds(118, 43, 98, 23); frmjavaSwing.getContentPane().add(btnK3); JButton btnK4 = new JButton("RGB2Luv"); btnK4.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(colorSpaceConversion(source,4)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btnK4.setBounds(226, 10, 100, 23); frmjavaSwing.getContentPane().add(btnK4); JButton btnK5 = new JButton("RGB2YUV"); btnK5.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(colorSpaceConversion(source,5)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btnK5.setBounds(226, 43, 100, 23); frmjavaSwing.getContentPane().add(btnK5); JButton btnK6 = new JButton("RGB2YCrCb"); btnK6.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(colorSpaceConversion(source,6)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btnK6.setBounds(336, 10, 110, 23); frmjavaSwing.getContentPane().add(btnK6); JButton btnK7 = new JButton("RGB2XYZ"); btnK7.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { BufferedImage newImage=matToBufferedImage(colorSpaceConversion(source,7)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); btnK7.setBounds(336, 43, 98, 23); frmjavaSwing.getContentPane().add(btnK7); } public Mat colorSpaceConversion(Mat source,int type){ Mat destination=new Mat(source.rows(),source.cols(),source.type()); if (type==0){ Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2HLS); }else if (type==1){ Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2BGR); }else if (type==2){ Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2HSV); }else if (type==3){ Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2Lab); }else if (type==4){ Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2Luv); }else if (type==5){ Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2YUV); }else if (type==6){ Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2YCrCb); }else if (type==7){ Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2XYZ); } return destination; } public BufferedImage matToBufferedImage(Mat matrix) { int cols = matrix.cols(); int rows = matrix.rows(); int elemSize = (int)matrix.elemSize(); byte[] data = new byte[cols * rows * elemSize]; int type; matrix.get(0, 0, data); switch (matrix.channels()) { case 1: type = BufferedImage.TYPE_BYTE_GRAY; break; case 3: type = BufferedImage.TYPE_3BYTE_BGR; // bgr to rgb byte b; for(int i=0; i<data.length; i=i+3) { b = data[i]; data[i] = data[i+2]; data[i+2] = b; } break; default: return null; } BufferedImage image2 = new BufferedImage(cols, rows, type); image2.getRaster().setDataElements(0, 0, cols, rows, data); return image2; } }Result
- 投稿日:2019-05-21T14:08:38+09:00
Desktop : OpenCV EqualizeHist For YUV
Goal
Test OpenCV EqualizeHist with YUV channel.
OpenCV_ContrastUseEqualizeHistForYUV.javaimport org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; public class OpenCV_ContrastUseEqualizeHistForYUV { static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } private JFrame frmjavaSwing; double alpha = 2; double beta = 50; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { OpenCV_ContrastUseEqualizeHistForYUV window = new OpenCV_ContrastUseEqualizeHistForYUV(); window.frmjavaSwing.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the application. */ public OpenCV_ContrastUseEqualizeHistForYUV() { initialize(); } /** * Initialize the contents of the frame. */ private void initialize() { final Mat source = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\clean.jpg"); BufferedImage image=matToBufferedImage(equalizeHist(source)); frmjavaSwing = new JFrame(); frmjavaSwing.setTitle("opencv彩色影像對比練習3"); frmjavaSwing.setBounds(100, 100, 520, 550); frmjavaSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmjavaSwing.getContentPane().setLayout(null); final JLabel lblNewLabel = new JLabel(""); lblNewLabel.setBounds(10, 10, 438, 455); lblNewLabel.setIcon(new ImageIcon(image)); frmjavaSwing.getContentPane().add(lblNewLabel); } public Mat equalizeHist(Mat source){ Mat destination=new Mat(source.rows(),source.cols(),source.type()); Mat tempYUV=new Mat(source.rows(),source.cols(),source.type()); Imgproc.cvtColor(source, tempYUV, Imgproc.COLOR_RGB2YUV); List<Mat> yuvList = new ArrayList<Mat>(3); Core.split(tempYUV, yuvList); Imgproc.equalizeHist(yuvList.get(0), yuvList.get(0)); //Imgproc.equalizeHist(yuvList.get(1), yuvList.get(1)); //Imgproc.equalizeHist(yuvList.get(2), yuvList.get(2)); Core.merge(yuvList, destination); Imgproc.cvtColor(destination, destination, Imgproc.COLOR_YUV2RGB); return destination; } public BufferedImage matToBufferedImage(Mat matrix) { int cols = matrix.cols(); int rows = matrix.rows(); int elemSize = (int)matrix.elemSize(); byte[] data = new byte[cols * rows * elemSize]; int type; matrix.get(0, 0, data); switch (matrix.channels()) { case 1: type = BufferedImage.TYPE_BYTE_GRAY; break; case 3: type = BufferedImage.TYPE_3BYTE_BGR; // bgr to rgb byte b; for(int i=0; i<data.length; i=i+3) { b = data[i]; data[i] = data[i+2]; data[i+2] = b; } break; default: return null; } BufferedImage image2 = new BufferedImage(cols, rows, type); image2.getRaster().setDataElements(0, 0, cols, rows, data); return image2; } }Result
- 投稿日:2019-05-21T12:49:03+09:00
Desktop : OpenCV Use EqualizeHist With Add Weight For RGB
Goal
OpenCV_ContrastUseEqualizeHistWithAddWeightForRGB.javaimport org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; public class OpenCV_ContrastUseEqualizeHistWithAddWeightForRGB { static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);} private JFrame frmjavaSwing; double alpha =2; double beta = 2; double gamma=1; /** * Launch the application. */ public static void main(String[] args){ EventQueue.invokeLater(new Runnable() { @Override public void run() { try{ OpenCV_ContrastUseEqualizeHistWithAddWeightForRGB window = new OpenCV_ContrastUseEqualizeHistWithAddWeightForRGB(); window.frmjavaSwing.setVisible(true); }catch (Exception e){ e.printStackTrace(); } } }); } /** * Create the application. */ public OpenCV_ContrastUseEqualizeHistWithAddWeightForRGB(){ init(); } /** * Init the contents of the frame. */ private void init(){ final Mat source = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\clean.jpg"); BufferedImage image=matToBufferedImage(equalizeHist(source)); frmjavaSwing = new JFrame(); frmjavaSwing.setTitle("opencv彩色影像對比練習1"); frmjavaSwing.setBounds(100, 100, 520, 550); frmjavaSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmjavaSwing.getContentPane().setLayout(null); final JLabel lblNewLabel = new JLabel(""); lblNewLabel.setBounds(10, 10, 438, 455); lblNewLabel.setIcon(new ImageIcon(image)); frmjavaSwing.getContentPane().add(lblNewLabel); } public Mat equalizeHist(Mat source){ Mat destination=new Mat(source.rows(),source.cols(),source.type()); Mat source2=new Mat(source.rows(),source.cols(),source.type()); List<Mat> bgrList = new ArrayList<>(3); Core.split(source, bgrList); Imgproc.equalizeHist(bgrList.get(0), bgrList.get(0)); Imgproc.equalizeHist(bgrList.get(1), bgrList.get(1)); Imgproc.equalizeHist(bgrList.get(2), bgrList.get(2)); Core.merge(bgrList, destination); Core.addWeighted(source,alpha,source2,beta,gamma,destination); return destination; } public BufferedImage matToBufferedImage(Mat matrix) { int cols = matrix.cols(); int rows = matrix.rows(); int elemSize = (int)matrix.elemSize(); byte[] data = new byte[cols * rows * elemSize]; int type; matrix.get(0, 0, data); switch (matrix.channels()) { case 1: type = BufferedImage.TYPE_BYTE_GRAY; break; case 3: type = BufferedImage.TYPE_3BYTE_BGR; // bgr to rgb byte b; for(int i=0; i<data.length; i=i+3) { b = data[i]; data[i] = data[i+2]; data[i+2] = b; } break; default: return null; } BufferedImage image2 = new BufferedImage(cols, rows, type); image2.getRaster().setDataElements(0, 0, cols, rows, data); return image2; } }Result
- 投稿日:2019-05-21T12:38:52+09:00
OpenCV Contrast Use Equalize Hist For RBG
Goal
Test OpenCV Equalize Hist with split RGB channel then merge to original image.
OpenCV_ContrastUseEqualizeHistForRBG.javaimport java.awt.EventQueue; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; public class OpenCV_ContrastUseEqualizeHistForRBG { static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);} private JFrame frmjavaSwing; double alpha =2; double beta = 2; /** * Launch the application. */ public static void main(String[] args){ EventQueue.invokeLater(new Runnable() { @Override public void run() { try{ OpenCV_ContrastUseEqualizeHistForRBG window = new OpenCV_ContrastUseEqualizeHistForRBG(); window.frmjavaSwing.setVisible(true); }catch (Exception e){ e.printStackTrace(); } } }); } /** * Create the application. */ public OpenCV_ContrastUseEqualizeHistForRBG(){ init(); } /** * Init the contents of the frame. */ private void init(){ final Mat source = Imgcodecs.imread("D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\clean.jpg"); BufferedImage image=matToBufferedImage(equalizeHist(source)); frmjavaSwing = new JFrame(); frmjavaSwing.setTitle("opencv彩色影像對比練習1"); frmjavaSwing.setBounds(100, 100, 520, 550); frmjavaSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmjavaSwing.getContentPane().setLayout(null); final JLabel lblNewLabel = new JLabel(""); lblNewLabel.setBounds(10, 10, 438, 455); lblNewLabel.setIcon(new ImageIcon(image)); frmjavaSwing.getContentPane().add(lblNewLabel); } public Mat equalizeHist(Mat source){ Mat destination=new Mat(source.rows(),source.cols(),source.type()); List<Mat> bgrList = new ArrayList<>(3); Core.split(source, bgrList); Imgproc.equalizeHist(bgrList.get(0), bgrList.get(0)); Imgproc.equalizeHist(bgrList.get(1), bgrList.get(1)); Imgproc.equalizeHist(bgrList.get(2), bgrList.get(2)); Core.merge(bgrList, destination); return destination; } public BufferedImage matToBufferedImage(Mat matrix) { int cols = matrix.cols(); int rows = matrix.rows(); int elemSize = (int)matrix.elemSize(); byte[] data = new byte[cols * rows * elemSize]; int type; matrix.get(0, 0, data); switch (matrix.channels()) { case 1: type = BufferedImage.TYPE_BYTE_GRAY; break; case 3: type = BufferedImage.TYPE_3BYTE_BGR; // bgr to rgb byte b; for(int i=0; i<data.length; i=i+3) { b = data[i]; data[i] = data[i+2]; data[i+2] = b; } break; default: return null; } BufferedImage image2 = new BufferedImage(cols, rows, type); image2.getRaster().setDataElements(0, 0, cols, rows, data); return image2; } }
- 投稿日:2019-05-21T12:30:37+09:00
Desktop : OpenCV Affine
Goal
Test OpenCV affine.
OpenCV_WarpAffine.javaimport org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.MatOfPoint2f; import org.opencv.core.Point; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.image.BufferedImage; public class OpenCV_WarpAffine { static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);} private JFrame frmjavaSwing; double alpha =2; double beta =50; /** * Launch the application. */ public static void main(String[] args){ EventQueue.invokeLater(new Runnable() { @Override public void run() { try{ OpenCV_WarpAffine window = new OpenCV_WarpAffine(); window.frmjavaSwing.setVisible(true); }catch (Exception e){ e.printStackTrace(); } } }); } public OpenCV_WarpAffine(){ init(); } /** * Init the contents of the frame. */ private void init(){ final Mat src = Imgcodecs.imread( "D:\\projects\\Java\\OpenCV_Samples\\resource\\imgs\\clean.jpg"); BufferedImage image = matToBufferedImage(src); frmjavaSwing = new JFrame(); frmjavaSwing.setTitle("OpenCV 影像扭曲練習"); frmjavaSwing.setBounds(100, 100, 520, 550); frmjavaSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmjavaSwing.getContentPane().setLayout(null); final JLabel showDot1Value = new JLabel("0.1"); showDot1Value.setBounds(210, 10, 27, 15); frmjavaSwing.getContentPane().add(showDot1Value); final JLabel showDot2Value = new JLabel("0.1"); showDot2Value.setBounds(210, 35, 27, 15); frmjavaSwing.getContentPane().add(showDot2Value); final JLabel lblNewLabel = new JLabel(""); lblNewLabel.setBounds(10, 91, 438, 467); lblNewLabel.setIcon(new ImageIcon(image)); frmjavaSwing.getContentPane().add(lblNewLabel); final JSlider slider_Dot2 = new JSlider(); slider_Dot2.setMaximum(10); slider_Dot2.setValue(0); slider_Dot2.setBounds(47, 33, 162, 25); frmjavaSwing.getContentPane().add(slider_Dot2); final JSlider slider_Dot3 = new JSlider(); slider_Dot3.setMaximum(10); slider_Dot3.setValue(0); slider_Dot3.setBounds(47, 56, 162, 25); frmjavaSwing.getContentPane().add(slider_Dot3); final JSlider slider_Dot1 = new JSlider(); slider_Dot1.setMaximum(10); slider_Dot1.setValue(0); slider_Dot1.setBounds(47, 10, 162, 25); frmjavaSwing.getContentPane().add(slider_Dot1); JLabel lblAlpha = new JLabel("var1"); lblAlpha.setBounds(10, 20, 46, 15); frmjavaSwing.getContentPane().add(lblAlpha); JLabel lblBeta = new JLabel("var2"); lblBeta.setBounds(10, 45, 46, 15); frmjavaSwing.getContentPane().add(lblBeta); JLabel lblDot = new JLabel("var3"); lblDot.setBounds(10, 68, 27, 15); frmjavaSwing.getContentPane().add(lblDot); final JLabel showDot3Value = new JLabel("0.1"); showDot3Value.setBounds(210, 60, 25, 15); frmjavaSwing.getContentPane().add(showDot3Value); JLabel lblVar_2 = new JLabel("var6"); lblVar_2.setBounds(234, 66, 32, 15); frmjavaSwing.getContentPane().add(lblVar_2); JLabel lblVar_1 = new JLabel("var5"); lblVar_1.setBounds(234, 43, 32, 15); frmjavaSwing.getContentPane().add(lblVar_1); JLabel lblVar = new JLabel("var4"); lblVar.setBounds(234, 18, 32, 15); frmjavaSwing.getContentPane().add(lblVar); final JSlider slider_Dot4 = new JSlider(); slider_Dot4.setMaximum(10); slider_Dot4.setValue(0); slider_Dot4.setBounds(265, 10, 162, 25); frmjavaSwing.getContentPane().add(slider_Dot4); final JSlider slider_Dot5 = new JSlider(); slider_Dot5.setMaximum(10); slider_Dot5.setValue(0); slider_Dot5.setBounds(265, 35, 162, 25); frmjavaSwing.getContentPane().add(slider_Dot5); final JSlider slider_Dot6 = new JSlider(); slider_Dot6.setMaximum(10); slider_Dot6.setValue(0); slider_Dot6.setBounds(265, 56, 162, 25); frmjavaSwing.getContentPane().add(slider_Dot6); final JLabel showDot4Value = new JLabel("0.1"); showDot4Value.setBounds(437, 10, 27, 15); frmjavaSwing.getContentPane().add(showDot4Value); final JLabel showDot5Value = new JLabel("0.1"); showDot5Value.setBounds(437, 35, 27, 15); frmjavaSwing.getContentPane().add(showDot5Value); final JLabel showDot6Value = new JLabel("0.1"); showDot6Value.setBounds(437, 56, 27, 15); frmjavaSwing.getContentPane().add(showDot6Value); slider_Dot1.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { //System.out.println(slider_alpha.getValue()); showDot1Value.setText((float)slider_Dot1.getValue()/10+""); BufferedImage newImage=matToBufferedImage(wrap(src,slider_Dot1.getValue(),(float)slider_Dot2.getValue()/10,(float)slider_Dot3.getValue()/10,(float)slider_Dot4.getValue()/10,(float)slider_Dot5.getValue()/10,(float)slider_Dot6.getValue()/10)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); slider_Dot3.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { showDot3Value.setText((float)slider_Dot3.getValue()/10+""); BufferedImage newImage=matToBufferedImage(wrap(src,slider_Dot1.getValue(),(float)slider_Dot2.getValue()/10,(float)slider_Dot3.getValue()/10,(float)slider_Dot4.getValue()/10,(float)slider_Dot5.getValue()/10,(float)slider_Dot6.getValue()/10)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); slider_Dot2.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { showDot2Value.setText((float)slider_Dot2.getValue()/10+""); BufferedImage newImage=matToBufferedImage(wrap(src,slider_Dot1.getValue(),(float)slider_Dot2.getValue()/10,(float)slider_Dot3.getValue()/10,(float)slider_Dot4.getValue()/10,(float)slider_Dot5.getValue()/10,(float)slider_Dot6.getValue()/10)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); slider_Dot4.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { showDot4Value.setText((float)slider_Dot4.getValue()/10+""); BufferedImage newImage=matToBufferedImage(wrap(src,slider_Dot1.getValue(),(float)slider_Dot2.getValue()/10,(float)slider_Dot3.getValue()/10,(float)slider_Dot4.getValue()/10,(float)slider_Dot5.getValue()/10,(float)slider_Dot6.getValue()/10)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); slider_Dot5.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { showDot5Value.setText((float)slider_Dot5.getValue()/10+""); BufferedImage newImage=matToBufferedImage(wrap(src,slider_Dot1.getValue(),(float)slider_Dot2.getValue()/10,(float)slider_Dot3.getValue()/10,(float)slider_Dot4.getValue()/10,(float)slider_Dot5.getValue()/10,(float)slider_Dot6.getValue()/10)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); slider_Dot6.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent arg0) { showDot6Value.setText((float)slider_Dot6.getValue()/10+""); BufferedImage newImage=matToBufferedImage(wrap(src,slider_Dot1.getValue(),(float)slider_Dot2.getValue()/10,(float)slider_Dot3.getValue()/10,(float)slider_Dot4.getValue()/10,(float)slider_Dot5.getValue()/10,(float)slider_Dot6.getValue()/10)); lblNewLabel.setIcon(new ImageIcon(newImage)); } }); } public Mat wrap(Mat source,double dot1,double dot2,double dot3,double dot4,double dot5,double dot6){ Mat wrapMat=new Mat(2,3, CvType.CV_32FC1); Mat destination=new Mat(source.rows(),source.cols(),source.type()); MatOfPoint2f srcTri=new MatOfPoint2f(); MatOfPoint2f dstTri=new MatOfPoint2f(); Point[] srcPoints=new Point[3]; srcPoints[0]=new Point(0,0); srcPoints[1]=new Point(source.cols()-1,0); srcPoints[2]=new Point(0,source.rows()-1); srcTri.fromArray(srcPoints); Point[] dstPoints=new Point[3]; dstPoints[0]=new Point(source.cols()*dot1,source.rows()*dot2); dstPoints[1]=new Point(source.cols()*dot3,source.rows()*dot4); dstPoints[2]=new Point(source.cols()*dot5,source.rows()*dot6); dstTri.fromArray(dstPoints); wrapMat=Imgproc.getAffineTransform(srcTri, dstTri); Imgproc.warpAffine(source, destination, wrapMat, destination.size()); return destination; } public BufferedImage matToBufferedImage(Mat matrix) { int cols = matrix.cols(); int rows = matrix.rows(); int elemSize = (int)matrix.elemSize(); byte[] data = new byte[cols * rows * elemSize]; int type; matrix.get(0, 0, data); switch (matrix.channels()) { case 1: type = BufferedImage.TYPE_BYTE_GRAY; break; case 3: type = BufferedImage.TYPE_3BYTE_BGR; // bgr to rgb byte b; for(int i=0; i<data.length; i=i+3) { b = data[i]; data[i] = data[i+2]; data[i+2] = b; } break; default: return null; } BufferedImage image2 = new BufferedImage(cols, rows, type); image2.getRaster().setDataElements(0, 0, cols, rows, data); return image2; } }Result
- 投稿日:2019-05-21T08:08:24+09:00
WebViewとネイティブのメリットデメリット
App内で動作する簡易ブラウザ(WebView)と通信からUIまでアプリ内で完結するネイティブアプリのメリットデメリットをまとめてみました。
■WebViewのメリット・デメリット
メリット
コストが安い
Web上にコンテンツがあり、それを流用したい場合、新規で開発することなく同じコンテンツを表示できます。アプリストアへの申請・審査の不要
ネイティブアプリの申請や審査が不要になります。
※ただし、部分的なWebView表示の場合ネイティブと変わらないので審査は必要です。アプリアップデートの不要
アプリの保守をする必要がないため、アプリ自体のアップデートがありません。
※仕様が変更された時は、アプリの動作を変更する可能性があるため、一概ではないです。デメリット
課金ができない
Apple Store審査ガイドラインの規約違反になり、リジェクトされる恐れがあります。
※Webブラウザでの課金は可能(リンクをブラウザへ飛ばす必要あり)
引用:Apple Store審査ガイドライン:3.1.1 App内課金レスポンシブ対応
画面解像度に応じたUI設計の対応が必要。
Webの表示をそのまま、アプリに適応させると表示崩れが起こる可能性がある。脆弱性
自社以外の外部アクセス
URL直打ちで、自社ではないサイトにアクセスできる場合、悪用される恐れがある。
外部アクセスできるサイトに制限を設ける必要がある。端末内のファイルストリームにアクセスできる
「file://」で始まるURI(※URLではない)でアクセスすることで、端末内部のファイルにアクセスすることができる。
アクセスログからユーザー情報が漏洩されてしまう。iOSは、Cookieを保存しない
アプリが終了するとCookieが消えるので、永続化する必要がある
XSSの恐れ
攻撃スクリプトを入力できてしまう。
サニタイジング(無害化)する必要がある。通信エラー場合の表示
通信エラー場合のWebView画面を表示する前に、レスポンスチェックを行い、ネイティブの別画面を表示させる。
WebViewは通信した結果の表示なので、真っ白になったり、URLエラーになったりしてUI的に作りが悪い。環境によっては表示が遅い
Web通信が伴うため、通信環境によっては表示が遅い場合があります。■ネイティブ画面のメリット・デメリット
メリット
Webではできない画面設計・操作設計ができる
アプリ内のUIを使用するため、自由に画面設計を行うことが可能導線設計が可能
アプリに誘導できるセキュリティ
URL直打ちではないため、外部のサイトへアクセスさせることはないです。デメリット
コストが高い
iOS / Androidの開発者が必要
開発言語が異なるため、それぞれの開発者が必要アプリストアへの申請・審査
ネイティブアプリの申請や審査が必要です。アプリアップデートが必要
保守でアプリ修正があった場合は、アップデートが必要課金
App内課金を(30%)手数料(30%)が発生する引用
https://appbu.jp/webapps-nativeapps
https://ja.developer.box.com/docs/android-security-guidelines
https://appkitbox.com/knowledge/android/20130819-84
https://teratail.com/questions/100872
https://mexess.blog/2018/08/03/post-304/
https://qiita.com/noboru_i/items/240ffcb2036f3b5cbc3b
https://qiita.com/noboru_i/items/bc39d95638e9e55437fa#cookie%E3%81%AE%E8%A8%AD%E5%AE%9A
https://qiita.com/i_nak/items/be0fac91bdc68aa165db
https://backapp.co.jp/blog/11594/
https://support.ebis.ne.jp/search_service/15033/