Java tutorial
package net.bsrc.cbod.opencv; import java.io.File; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import net.bsrc.cbod.core.RegionMapFactory; import net.bsrc.cbod.core.model.CandidateComponent; import net.bsrc.cbod.core.model.EObjectType; import net.bsrc.cbod.core.model.ImageModel; import net.bsrc.cbod.core.model.RegionMap; import net.bsrc.cbod.core.util.CBODUtil; import net.bsrc.cbod.pascal.xml.PascalBndBox; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.Validate; import org.opencv.core.*; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.googlecode.javacpp.Pointer; import com.googlecode.javacv.cpp.opencv_core; import com.googlecode.javacv.cpp.opencv_core.CvMat; import static com.googlecode.javacv.cpp.opencv_core.*; /** * @author bsr */ public final class OpenCV { private static final Logger logger = LoggerFactory.getLogger(OpenCV.class); private OpenCV() { } /** * @param imgPath * @return */ public static Mat getImageMat(String imgPath) { Mat mat = Highgui.imread(imgPath); return mat; } public static Mat getImageMatAsGrayScale(String imgPath) { Mat mat = Highgui.imread(imgPath, Highgui.CV_LOAD_IMAGE_GRAYSCALE); return mat; } /** * @param imageModel * @return */ public static Mat getImageMat(ImageModel imageModel) { Validate.notNull(imageModel, "Imagemodel must not be null"); return getImageMat(imageModel.getImagePath()); } public static Mat getImageMatAsGrayScale(ImageModel imageModel) { Validate.notNull(imageModel, "Imagemodel must not be null"); return getImageMatAsGrayScale(imageModel.getImagePath()); } /** * @param imgPath * @param box * @return */ public static Mat getImageMat(String imgPath, PascalBndBox box) { Mat result = null; Mat org = getImageMat(imgPath); Point[] arr = new Point[] { new Point(box.getXmin(), box.getYmin()), new Point(box.getXmin(), box.getYmax() - 1), new Point(box.getXmax() - 1, box.getYmin()), new Point(box.getXmax() - 1, box.getYmax() - 1) }; try { Rect r = Imgproc.boundingRect(new MatOfPoint(arr)); result = org.submat(r); } catch (CvException ex) { logger.error("", ex); } return result; } /** * @param m * @param imgPath */ public static void writeImage(Mat m, String imgPath) { File file = FileUtils.getFile(imgPath); File parent = file.getParentFile(); if (!parent.exists()) { CBODUtil.createDirectory(parent); } Highgui.imwrite(imgPath, m); } public static void drawRect(Rect rect, Mat mat) { drawRect(rect, mat, null); } public static void drawRect(Rect rect, Mat mat, Scalar scalar) { Point p1 = new Point(rect.x, rect.y); Point p2 = new Point(rect.x + rect.width, rect.y); Point p3 = new Point(rect.x + rect.width, rect.y + rect.height); Point p4 = new Point(rect.x, rect.y + rect.height); if (scalar == null) scalar = new Scalar(0, 255, 0); Core.line(mat, p1, p2, scalar, 2); Core.line(mat, p2, p3, scalar, 2); Core.line(mat, p3, p4, scalar, 2); Core.line(mat, p4, p1, scalar, 2); } public static void drawComponentsToImage(List<CandidateComponent> candidateComponents, ImageModel imageModel, String outputSuffix) { Mat copy = OpenCV.copyImage(imageModel.getMat()); Scalar blue = new Scalar(255, 0, 0); Scalar green = new Scalar(0, 255, 0); Scalar red = new Scalar(0, 0, 255); if (candidateComponents != null) { for (CandidateComponent cc : candidateComponents) { Rect rect = cc.getRect(); if (cc.getObjectType().equals(EObjectType.WHEEL)) { OpenCV.drawRect(rect, copy, red); } if (cc.getObjectType().equals(EObjectType.TAIL_LIGHT)) { OpenCV.drawRect(rect, copy, green); } if (cc.getObjectType().equals(EObjectType.LICENSE_PLATE)) { OpenCV.drawRect(rect, copy, blue); } } } String outputImagePath = CBODUtil.getCbodTempDirectory().concat("/") .concat(imageModel.getRawImageName() + outputSuffix + "." + imageModel.getExtension()); OpenCV.writeImage(copy, outputImagePath); } private static void drawComponentsToImage(List<CandidateComponent> candidateComponents, CandidateComponent pivot, ImageModel imageModel, String outputSuffix, double fuzzyResult, boolean writeFuzzyResult) { Mat copy = OpenCV.copyImage(imageModel.getMat()); Scalar blue = new Scalar(255, 0, 0); Scalar green = new Scalar(0, 255, 0); Scalar red = new Scalar(0, 0, 255); Scalar yellow = new Scalar(0, 255, 255); if (candidateComponents != null) { for (CandidateComponent cc : candidateComponents) { Rect rect = cc.getRect(); if (cc.getObjectType().equals(EObjectType.WHEEL)) { OpenCV.drawRect(rect, copy, red); } if (cc.getObjectType().equals(EObjectType.TAIL_LIGHT)) { OpenCV.drawRect(rect, copy, green); } if (cc.getObjectType().equals(EObjectType.LICENSE_PLATE)) { OpenCV.drawRect(rect, copy, blue); } } } if (pivot != null) { OpenCV.drawRect(pivot.getRect(), copy, yellow); } if (writeFuzzyResult) { DecimalFormat dFormat = new DecimalFormat("#.####"); drawText(copy, new Point(5, 20), dFormat.format(fuzzyResult)); } String outputImagePath = CBODUtil.getCbodTempDirectory().concat("/") .concat(imageModel.getRawImageName() + outputSuffix + "." + imageModel.getExtension()); OpenCV.writeImage(copy, outputImagePath); } public static void drawComponentsToImage(List<CandidateComponent> candidateComponents, CandidateComponent pivot, ImageModel imageModel, String outputSuffix) { drawComponentsToImage(candidateComponents, pivot, imageModel, outputSuffix, 0.0, false); } public static void drawComponentsToImage(List<CandidateComponent> candidateComponents, CandidateComponent pivot, ImageModel imageModel, String outputSuffix, double fuzzyResult) { drawComponentsToImage(candidateComponents, pivot, imageModel, outputSuffix, fuzzyResult, true); } public static void drawText(Mat m, Point p, String text) { Core.putText(m, text, p, Core.FONT_HERSHEY_SIMPLEX, 0.75, new Scalar(238, 130, 238), 2); } public static Point getCenterPoint(Rect rect) { double centerX = rect.x + (rect.width / 2.0); double centerY = rect.y + (rect.height / 2.0); return new Point(centerX, centerY); } /** * @param imagePath name of the orginal image * @param mapFilePath name of the orginal image's map file * @return */ public static List<Mat> getSegmentedRegions(String imagePath, String mapFilePath, boolean isBlackBg) { Mat org = getImageMat(imagePath); RegionMap regionMap = RegionMapFactory.getRegionMap(imagePath, mapFilePath); List<Mat> result = new ArrayList<Mat>(); Mat map = regionMap.getMap(); for (Integer label : regionMap.getLabels()) { List<Point> points = new ArrayList<Point>(); for (int i = 0; i < map.rows(); i++) { for (int j = 0; j < map.cols(); j++) { double[] temp = map.get(i, j); if (temp[0] == label) { // Warning! col=x=j , row=y=i points.add(new Point(j, i)); } } } Point[] arr = points.toArray(new Point[points.size()]); Rect rect = Imgproc.boundingRect(new MatOfPoint(arr)); Mat region; if (isBlackBg) { region = getImageWithBlackBg(org, points).submat(rect); } else { region = org.submat(rect); } result.add(region); } return result; } /** * @param imagePath * @param mapFilePath * @param isBlackBg * @return */ public static List<ImageModel> getSegmentedRegionsAsImageModels(String imagePath, String mapFilePath, boolean isBlackBg) { Mat org = getImageMat(imagePath); RegionMap regionMap = RegionMapFactory.getRegionMap(imagePath, mapFilePath); List<ImageModel> result = new ArrayList<ImageModel>(); Mat map = regionMap.getMap(); for (Integer label : regionMap.getLabels()) { List<Point> points = new ArrayList<Point>(); for (int i = 0; i < map.rows(); i++) { for (int j = 0; j < map.cols(); j++) { double[] temp = map.get(i, j); if (temp[0] == label) { // Warning! col=x=j , row=y=i points.add(new Point(j, i)); } } } Point[] arr = points.toArray(new Point[points.size()]); Rect rect = null; try { rect = Imgproc.boundingRect(new MatOfPoint(arr)); } catch (Exception ex) { logger.error("", ex); continue; } Mat region; if (isBlackBg) { region = getImageWithBlackBg(org, points).submat(rect); } else { region = org.submat(rect); } ImageModel imgModel = new ImageModel(); imgModel.setMat(region); imgModel.setRelativeToOrg(rect); result.add(imgModel); } return result; } public static Mat copyImage(Mat org) { Mat copy = new Mat(); org.copyTo(copy); return copy; } /** * Helper method * * @param org * @param list * @return */ private static Mat getImageWithBlackBg(Mat org, List<Point> list) { Mat region = Mat.zeros(org.size(), org.type()); for (Point p : list) { int row = (int) p.y; int col = (int) p.x; region.put(row, col, org.get(row, col)); } return region; } /* * public static CvMat concatenateDescriptors(List<CvMat> descriptorsList, * int index) { if (descriptorsList.size() == (index + 1)) { return * descriptorsList.get(index); } else { CvMat head = * descriptorsList.get(index); CvMat next = * concatenateDescriptors(descriptorsList, index + 1); CvMat desc = * cvCreateMat(head.rows() + next.rows(), head.cols(), next.type()); * desc.put(head); int offset = head.rows(); for (int i = offset; i < * desc.rows(); i++) { for (int j = 0; j < desc.cols(); j++) { desc.put(i, * j, next.get(i - offset, j)); } } return desc; } } */ public static CvMat concatenateDescriptors(List<CvMat> descriptorsList, int type) { CvMat concated = null; int maxCol = 0; int totalRow = 0; for (CvMat mat : descriptorsList) { totalRow = totalRow + mat.rows(); if (maxCol == 0) { maxCol = mat.cols(); continue; } if (maxCol < mat.cols()) maxCol = mat.cols(); } int rows = totalRow; int cols = maxCol; concated = CvMat.create(rows, cols, type); int globalRows = 0; for (CvMat mat : descriptorsList) { for (int i = 0; i < mat.rows(); i++) { for (int j = 0; j < mat.cols(); j++) { concated.put(globalRows, j, mat.get(i, j)); } globalRows++; } } return concated; } public static void storeCvMatToFile(String filePath, String varName, CvMat mat) { CvFileStorage fileStorage = cvOpenFileStorage(filePath, null, CV_STORAGE_WRITE, null); cvWrite(fileStorage, varName, mat); cvReleaseFileStorage(fileStorage); } public static CvMat loadCvMatFromFile(String filePath, String varName) { CvMat result = null; CvFileStorage fileStorage = cvOpenFileStorage(filePath, null, CV_STORAGE_READ, null); if (fileStorage == null) { logger.error("File could not be opened:{}", filePath); return null; } Pointer pointer = cvReadByName(fileStorage, null, varName); result = new CvMat(pointer); return result; } public static double getMinimumDistance(Rect r1, Rect r2) { double result = 0.0; if (intersect(r1, r2)) { return result; } Point o1 = getCenterPoint(r1); Point o2 = getCenterPoint(r2); if (o1.x == o2.x) { //r1:upper r2:lower or r1:lower and r2:upper result = Math.abs(o2.y - o1.y) - ((r1.height / 2.0) + (r2.height / 2.0)); } if (o1.y == o2.y) { //r1:left r2:right or r1:right r2:left result = Math.abs(o2.x - o1.x) - ((r1.width / 2.0) + (r2.width / 2.0)); } //r1:left r2:right if (o1.x < o2.x) { //r1:upper r2:lower if (o1.y < o2.y) { Point p1_2 = getPoint(r1, 2); Point p2_0 = getPoint(r2, 0); if (p1_2.x <= p2_0.x && p1_2.y <= p2_0.y) { result = distance(p1_2, p2_0); } if (p1_2.x > p2_0.x && p1_2.y < p2_0.y) { result = p2_0.y - p1_2.y; } if (p1_2.x < p2_0.x && p1_2.y > p2_0.y) { result = p2_0.x - p1_2.x; } } //r1:lower r2:upper if (o1.y > o2.y) { Point p1_1 = getPoint(r1, 1); Point p2_3 = getPoint(r2, 3); if (p1_1.x <= p2_3.x && p1_1.y >= p2_3.y) { result = distance(p1_1, p2_3); } if (p1_1.x < p2_3.x && p1_1.y < p2_3.y) { result = p2_3.x - p1_1.x; } if (p1_1.x > p2_3.x && p1_1.y > p2_3.y) { result = p1_1.y - p2_3.y; } } } //r1:right r2:left if (o1.x > o2.x) { //r1:upper r2:lower if (o1.y < o2.y) { Point p1_3 = getPoint(r1, 3); Point p2_1 = getPoint(r2, 1); if (p1_3.x >= p2_1.x && p1_3.y <= p2_1.y) { result = distance(p1_3, p2_1); } if (p1_3.x > p2_1.x && p1_3.y > p2_1.y) { result = p1_3.x - p2_1.x; } if (p1_3.x < p2_1.x && p1_3.y < p2_1.y) { result = p2_1.y - p1_3.y; } } //r1:lower r2:upper if (o1.y > o2.y) { Point p1_0 = getPoint(r1, 0); Point p2_2 = getPoint(r2, 2); if (p1_0.x >= p2_2.x && p1_0.y >= p2_2.y) { result = distance(p1_0, p2_2); } if (p1_0.x > p2_2.x && p1_0.y < p2_2.y) { result = p1_0.x - p2_2.x; } if (p1_0.x < p2_2.x && p1_0.y > p2_2.y) { result = p1_0.y - p2_2.y; } } } return result; } public static double distance(Point p1, Point p2) { return Math.sqrt(Math.pow(Math.abs(p1.x - p2.x), 2) + Math.pow(Math.abs(p1.y - p2.y), 2)); } public static boolean intersect(Rect r1, Rect r2) { Point[] points1 = getCornerPoints(r1); Point[] points2 = getCornerPoints(r2); for (int i = 0; i < points1.length; i++) { if (r2.contains(points1[i])) { return true; } } for (int i = 0; i < points2.length; i++) { if (r1.contains(points2[i])) { return true; } } return false; } public static Rect createRect(int x, int y, int width, int height) { Rect r = new Rect(); r.x = x; r.y = y; r.width = width; r.height = height; return r; } /** * 0------1 * | | * | | * 3------2 */ public static Point[] getCornerPoints(Rect rect) { Point[] arr = new Point[] { new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Point(rect.x, rect.y + rect.height) }; return arr; } /** * 0------1 * | | * | | * 3------2 */ public static double getCornerX(Rect r, int index) { return getCornerPoints(r)[index].x; } /** * 0------1 * | | * | | * 3------2 */ public static double getCornerY(Rect r, int index) { return getCornerPoints(r)[index].y; } public static Point getPoint(Rect r, int index) { return getCornerPoints(r)[index]; } /** * @param p1 source * @param p2 target * @return */ public static double getAngle(Point p1, Point p2) { double angle = Math.toDegrees(Math.atan2((p2.y - p1.y), (p2.x - p1.x))); if (p2.y < p1.y) { angle = angle * (-1); } else { angle = 360 - angle; } return angle; } /** * @param r1 source * @param r2 target * @return */ public static double getAngle(Rect r1, Rect r2) { return getAngle(getCenterPoint(r1), getCenterPoint(r2)); } }