Created
May 11, 2017 13:11
-
-
Save threepipes/3b8704bfdfd86dd9d58837ef87656fa6 to your computer and use it in GitHub Desktop.
麻雀牌画像から牌の輪郭を切り出す
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.util.ArrayList; | |
| import java.util.List; | |
| import org.opencv.core.Core; | |
| import org.opencv.core.Mat; | |
| import org.opencv.core.Scalar; | |
| import org.opencv.core.Size; | |
| import org.opencv.imgcodecs.Imgcodecs; | |
| import org.opencv.imgproc.Imgproc; | |
| public class Recognizer { | |
| public static void main(String[] args) { | |
| System.loadLibrary(Core.NATIVE_LIBRARY_NAME); | |
| String srcfile = "in.webp"; | |
| Recognizer recog = new Recognizer(); | |
| Mat[] img = recog.recog2(srcfile); | |
| dump(img); | |
| } | |
| public static void dump(Mat[] images) { | |
| for(int i = 0; i < images.length; i++) { | |
| Imgcodecs.imwrite(String.format("data/img_%02d.png", i), images[i]); | |
| } | |
| } | |
| private int loss(byte[] data) { | |
| int loss = 0; | |
| for(int i = 0; i < data.length; i++) { | |
| loss += sq(data[i] - data[(i + 1) % data.length]); | |
| } | |
| return loss; | |
| } | |
| private int sq(int a) { | |
| return a * a; | |
| } | |
| private Mat minMat(Mat rgbImg) { | |
| List<Mat> rgb = new ArrayList<>(); | |
| Core.split(rgbImg, rgb); | |
| Mat r = rgb.get(0); | |
| Mat g = rgb.get(1); | |
| Mat b = rgb.get(2); | |
| Core.min(r, g, g); | |
| Core.min(g, b, b); | |
| return b; | |
| } | |
| public Mat[] recog2(String filename) { | |
| Mat image = Imgcodecs.imread(filename); | |
| Mat buffer = new Mat(); | |
| Imgproc.cvtColor(image, buffer, Imgproc.COLOR_RGB2HSV); | |
| Mat minImg = minMat(image); | |
| Mat minBW = new Mat(); | |
| Imgproc.threshold(minImg, minBW, 0, 255, Imgproc.THRESH_OTSU); | |
| List<Mat> channels = new ArrayList<>(); | |
| Core.split(image.clone(), channels); | |
| Mat sum = new Mat(); | |
| channels.stream().forEach(e -> Core.multiply(e, new Scalar(1.0 / 3), e)); | |
| Core.add(channels.get(0), channels.get(1), sum); | |
| Core.add(channels.get(2), sum, sum); | |
| Imgproc.Canny(sum, sum, 10, 100); | |
| return new Mat[]{sum}; | |
| } | |
| public Mat[] recognize(String filename) { | |
| Mat image = Imgcodecs.imread(filename); | |
| Mat buffer = new Mat(); | |
| Imgproc.cvtColor(image, buffer, Imgproc.COLOR_RGB2HSV); | |
| Mat minImg = minMat(image); | |
| Mat minBW = new Mat(); | |
| Imgproc.threshold(minImg, minBW, 0, 255, Imgproc.THRESH_OTSU); | |
| Mat imgW = new Mat(); // 背景消去用 | |
| int size = 3; | |
| Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2 * size + 1, 2 * size + 1)); | |
| Imgproc.dilate(minBW, imgW, element); | |
| Imgproc.erode(imgW, imgW, element); | |
| Mat imgB = new Mat(); // 文字消去用 | |
| size = 2; | |
| element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2 * size + 1, 2 * size + 1)); | |
| Imgproc.erode(minBW, imgB, element); | |
| Mat imgWinv = new Mat(); | |
| Core.bitwise_not(imgW, imgWinv); | |
| Mat mask = new Mat(); | |
| Core.bitwise_or(imgWinv, imgB, mask); | |
| Mat test = new Mat(); | |
| Core.bitwise_not(minBW, test); | |
| Core.bitwise_and(test, imgW, imgW); | |
| size = 1; | |
| element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2 * size + 1, 2 * size + 1)); | |
| Imgproc.dilate(test, test, element); | |
| // Imgproc.dilate(imgB, imgB, element); | |
| List<Mat> channels = new ArrayList<>(); | |
| Core.split(buffer, channels); | |
| Mat hImg = channels.get(0); // 色相 | |
| Mat sImg = channels.get(1); // 彩度 -> マスク用 | |
| Mat vImg = minImg; // 明度 -> 輪郭検出 | |
| Core.multiply(vImg, vImg, vImg, 1.0 / 255); | |
| Core.multiply(vImg, vImg, vImg, 1.0 / 255); | |
| // Core.bitwise_or(vImg, test, vImg); | |
| hImg = vImg.clone(); | |
| Imgproc.Canny(vImg, vImg, 100, 200); | |
| Core.bitwise_not(sImg, sImg); | |
| Core.multiply(sImg, sImg, sImg, 1.0 / 255); | |
| Core.multiply(sImg, sImg, sImg, 1.0 / 255); | |
| Imgproc.threshold(sImg, sImg, 0, 255, Imgproc.THRESH_OTSU); | |
| Mat bitImg = new Mat(); | |
| Core.bitwise_and(sImg, vImg, bitImg); | |
| Core.bitwise_not(test, test); | |
| Core.bitwise_and(vImg, test, mask); | |
| // return new Mat[]{hImg, sImg, vImg, bitImg}; | |
| return new Mat[]{minImg, minBW, imgW, imgB, mask, test}; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment