import org.opencv.core.*; import org.opencv.core.Point; import org.opencv.highgui.HighGui; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import static org.opencv.imgcodecs.Imgcodecs.imwrite; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.io.File; import javax.imageio.ImageIO; //REFERENCES: //https://docs.opencv.org/3.4.3/d9/db0/tutorial_hough_lines. //https://stackoverflow.com/questions/43443309/count-red-pixel-in-a-given-image //https://www.wikihow.com/Calculate-Percentage-in-Java //https://riptutorial.com/opencv/example/21963/converting-an-mat-object-to-an-bufferedimage-object //GOAL for 21st //Classifier 01 //Have args so can call "java image-identification-classifier01 XX XX" //args can be parameters in algorthim such as threshold or theta? //Run on 5000 images. //Record success rates //All done with makefile //But first understand houghline transform //Know what the algorithm being used is doing. //MAke constants for this classifier //Make java be able to run on CMD line public class terminalImageClassifier { //GLOBAL_CONSTANTS //SHOULD TURN INTO ARGS private static BufferedImage toBufferedImage(Mat mat){ //MOSTLY COPY PASTE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //MOSTLY COPY PASTE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //https://riptutorial.com/opencv/example/21963/converting-an-mat-object-to-an-bufferedimage-object try{ int type = BufferedImage.TYPE_3BYTE_BGR; int bufferSize = mat.channels() * mat.cols() * mat.rows(); byte[] b = new byte[bufferSize]; //get all the pixels mat.get(0, 0, b); BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type); final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); System.arraycopy(b, 0, targetPixels, 0, b.length); return image; } catch(Exception e){ System.err.println(e); } return null; } private static boolean Classifier(BufferedImage img){ try { //Read file //BufferedImage img = ImageIO.read(new File(processedFile)); int x = img.getWidth(); int y = img.getHeight(); int pixelCount = 0; int redCount = 0; float percentage = 0; //Go Thru every pixel for(int i=0; i < y; i++){ for(int j=0;j < x; j++){ //Get value for current pixels RGB value int currPixelRGB = img.getRGB(j, i); //Check if pixel is red (hex value of red) if(currPixelRGB == 0xFFFF0000){ redCount++; } pixelCount++; } } //Calculate percentage of Red in image percentage = ((float)redCount/(float)pixelCount)*(float)100; //If more than %10 and less than %50 then its sheet music! if(percentage > 10 && percentage < 50){ //MAKE THESE CONSTANTS!! return true;} } catch (Exception e) { System.err.println(e); } return false; } public static void main(String[] args) { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); try { //Variables Mat edgesDetected = new Mat(); Mat edgesDetectedRGB = new Mat(); Mat edgesDetectedRGBProb; Mat justEdges; //TESTING String default_file = "Test02.png"; String filename = ((args.length > 0) ? args[0] : default_file); // Load an image Mat original = Imgcodecs.imread(filename, Imgcodecs.IMREAD_GRAYSCALE); // Edge detection Imgproc.Canny(original, edgesDetected, 50, 200, 3, false); //Copy edges to the images that will display the results in BGR Imgproc.cvtColor(edgesDetected, edgesDetectedRGB, Imgproc.COLOR_GRAY2BGR); edgesDetectedRGBProb = edgesDetectedRGB.clone(); justEdges = edgesDetectedRGBProb.clone();//TESTING // Standard Hough Line Transform Mat lines = new Mat(); // will hold the results of the detection //(edgeDetectedImage, outputOfDetection(r,θ), resolution of r, resolution of θ, threshold (minimum num of intersections) Imgproc.HoughLines(edgesDetected, lines, 1.4, Math.PI / 180, 500); // runs the actual detection // Draw the lines //LOOK OVER THIS AGAIN THE 1000 might be image height? //THRESHOLD should be changed, based on img dimensions? for (int x = 0; x < lines.rows(); x++) { double rho = lines.get(x, 0)[0], theta = lines.get(x, 0)[1]; //CONVERT to Cartisean coord double a = Math.cos(theta), b = Math.sin(theta); double x0 = a * rho, y0 = b * rho; Point pt1 = new Point(Math.round(x0 + 1000 * (-b)), Math.round(y0 + 1000 * (a))); Point pt2 = new Point(Math.round(x0 - 1000 * (-b)), Math.round(y0 - 1000 * (a))); Imgproc.line(edgesDetectedRGB, pt1, pt2, new Scalar(0, 0, 255), 3, Imgproc.LINE_AA, 0); } // Probabilistic Line Transform Mat linesP = new Mat(); // will hold the results of the detection Imgproc.HoughLinesP(edgesDetected, linesP, 1, Math.PI / 180, 50, 50, 10); // runs the actual detection // Draw the lines for (int x = 0; x < linesP.rows(); x++) { double[] l = linesP.get(x, 0); Imgproc.line(edgesDetectedRGBProb, new Point(l[0], l[1]), new Point(l[2], l[3]), new Scalar(0, 0, 255), 3, Imgproc.LINE_AA, 0); } //Convert MAT into a BufferedImage BufferedImage toBeClassifiedImg = toBufferedImage(edgesDetectedRGBProb); //Calculate if its sheet music or not Boolean isSheetMusic = Classifier(toBeClassifiedImg); System.out.println("Filename: " + filename + " Status: " + isSheetMusic); //Save Processed Image String processedFile = null; if (isSheetMusic == true) { //NEED FIGURE OUT HOW RUN IN SCRIPT. THEN USE ARGS as filename + "HoughLineP + "png" processedFile = "SheetMusic/Test_HoughLineP.png"; }else { processedFile = "Test_HoughLineP.png"; } imwrite(processedFile, edgesDetectedRGBProb); //Display Results //HighGui.imshow("Source", original); HighGui.imshow("Just Edges", justEdges); //TESTING HighGui.imshow("Detected Lines (in red) - Standard Hough Line Transform", edgesDetectedRGB); //HighGui.imshow("Detected Lines (in red) - Probabilistic Line Transform", edgesDetectedRGBProb); // Wait and Exit HighGui.waitKey(); System.exit(0); } catch(Exception e){ System.err.println(e); } } }