Skip to content

Instantly share code, notes, and snippets.

@threepipes
Created May 11, 2017 13:11
Show Gist options
  • Select an option

  • Save threepipes/3b8704bfdfd86dd9d58837ef87656fa6 to your computer and use it in GitHub Desktop.

Select an option

Save threepipes/3b8704bfdfd86dd9d58837ef87656fa6 to your computer and use it in GitHub Desktop.
麻雀牌画像から牌の輪郭を切り出す
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