Как заставить OpevCv воспроизводить несколько кадров в одном и том же кадре - PullRequest
0 голосов
/ 15 марта 2020

Вся моя проблема в этой части (закрытый класс IconButtonHandler). Как получить все кадры для воспроизведения в одном кадре? Я устал создавать один jframe в классе, а затем добавлять к нему значки изображений внутри камеры с надписью l oop, однако jframe остается белым и показывает только последний кадр. Кто-нибудь может помочь?

class VideoDecoder {

    int frame_number;
    int frames_per_second;
    int video_length;
    String videoFilename;
    VideoCapture camera;
    int intensityBins[] = new int[25];
    int intensityMatrix[][];
    double distance[];
    double ts;
    double tb;
    int tor = 2;

    public VideoDecoder(String videoFilename) {
        this.videoFilename = videoFilename;
    }

    public void initialize() {
        if (!Paths.get(this.videoFilename).toFile().exists()) {
            System.out.println("File " + this.videoFilename + " does not exist!");
            return;
        }
        camera = new VideoCapture(this.videoFilename);

        if (!camera.isOpened()) {
            System.out.println("Error! Camera can't be opened!");
            return;
        } else {
            video_length = (int) camera.get(Videoio.CAP_PROP_FRAME_COUNT);
            frames_per_second = (int) camera.get(Videoio.CAP_PROP_FPS);
            frame_number = (int) camera.get(Videoio.CAP_PROP_POS_FRAMES);
        }
    }

    public void seek(int i) {
        camera.set(Videoio.CAP_PROP_POS_FRAMES, i);
        frame_number = (int) camera.get(Videoio.CAP_PROP_POS_FRAMES);
    }

    public void getIntensity(BufferedImage image, int height, int width, int imageCount) {
        for (int x = 0; x < width; x = x + 1) { // nested for loop to go over each pixel in each image, going over width
            for (int y = 0; y < height; y = y + 1) { // going over height
                Color mycolor = new Color(image.getRGB(x, y)); // get RGB values in a new color object
                double I = (0.299 * mycolor.getRed()) + (0.587 * mycolor.getGreen()) + (0.114 * mycolor.getBlue()); // calculate the 
                //intensity of the pixel as per the equation in the assignment
                //System.out.println("Intensity is " + I + " for x=" + x + " and y=" + y); // print the intensity of each pixel
                if (I <= 10) { // if statements to create the intinsity bins, increement the bin value if the intensity falls into the bin intensity range
                    intensityBins[0]++;
                } else if (I <= 20) {
                    intensityBins[1]++;
                } else if (I <= 30) {
                    intensityBins[2]++;
                } else if (I <= 40) {
                    intensityBins[3]++;
                } else if (I <= 50) {
                    intensityBins[4]++;
                } else if (I <= 60) {
                    intensityBins[5]++;
                } else if (I <= 70) {
                    intensityBins[6]++;
                } else if (I <= 80) {
                    intensityBins[7]++;
                } else if (I <= 90) {
                    intensityBins[8]++;
                } else if (I <= 100) {
                    intensityBins[9]++;
                } else if (I <= 110) {
                    intensityBins[10]++;
                } else if (I <= 120) {
                    intensityBins[11]++;
                } else if (I <= 130) {
                    intensityBins[12]++;
                } else if (I <= 140) {
                    intensityBins[13]++;
                } else if (I <= 150) {
                    intensityBins[14]++;
                } else if (I <= 160) {
                    intensityBins[15]++;
                } else if (I <= 170) {
                    intensityBins[16]++;
                } else if (I <= 180) {
                    intensityBins[17]++;
                } else if (I <= 190) {
                    intensityBins[18]++;
                } else if (I <= 200) {
                    intensityBins[19]++;
                } else if (I <= 210) {
                    intensityBins[20]++;
                } else if (I <= 220) {
                    intensityBins[21]++;
                } else if (I <= 230) {
                    intensityBins[22]++;
                } else if (I <= 240) {
                    intensityBins[23]++;
                } else if (I <= 255) {
                    intensityBins[24]++;
                }
            }
        }        
        for (int p = 0; p < 25; p++) { // for loop to copy the array into the intensity matrix
            intensityMatrix[imageCount][p] = intensityBins[p]; // copy the intensity bin array for the current image to its row in the bigger intensity matrix
            intensityBins[p] = 0; // reset the intensity matrix before running sgain on the next image
        }
    }

    public void getIntensityMatrix(int startFrame, int endFrame) {
        this.intensityMatrix = new int[(endFrame - 1000) + 1][25];        
        Mat frame = new Mat();
        while (camera.read(frame)) //the last frame of the movie will be invalid. check for it !
        {
            try {
                BufferedImage image;
                if (frame_number >= 1000 && frame_number <= endFrame) {

                    Imgcodecs.imwrite("x.jpg", frame);
                    image = ImageIO.read(new File("x.jpg")); // read each image sequential
                    int width = image.getWidth(); // get picture width to be used at getIntensity and getcolorCode functions
                    int height = image.getHeight();
                    getIntensity(image, height, width, frame_number - 1000);
                    frame_number++;                    
                } else {
                    break;
                }
            } catch (IOException e) {
                System.out.println("Error occurred when reading the file."); // printed if an exception is caught
            }
        }
    }

    public double getStandardDeviation(double[] distArray) {
        int rows = distArray.length;
        //System.out.println("rows in STD function is " + rows);
        int columns = distArray.length;
        //double[] average = new double[columns];
        double average = getAverage(distArray);
        double std = 0;
        double stdd = 0;
        for (int p = 0; p < columns; p++) {
            stdd += Math.pow((distArray[p] - average), 2); // calculate the standard deviation

        }
        std = Math.sqrt(stdd / (rows - 1));
        System.out.println("std is " + std);
        return std;
    }

    public double calculateSD(double distArray[]) {
        double sum = 0.0, standardDeviation = 0.0;
        int length = distArray.length;
        for (double num : distArray) {
            sum += num;
        }
        double mean = sum / length;
        for (double num : distArray) {
            standardDeviation += Math.pow(num - mean, 2);
        }
        System.out.println("StandardDev is " + Math.sqrt(standardDeviation / length));
        return Math.sqrt(standardDeviation / length);
    }

    public double getAverage(double[] distArray) {
        int columns = distArray.length;
        double average = 0;
        double sum = 0;
        for (int p = 0; p < columns; p++) {
            sum += distArray[p];
        }
        average = sum / columns;
        return average;
    }

    public double getTb() {
        double Tb = 0;       
        Tb = getAverage(distance) + getStandardDeviation(distance) * 11;
        System.out.println("Tb is " + Tb);
        return Tb;
    }

    public double getTs() {
        double Ts = 0;
        Ts = getAverage(distance) * 2;
        System.out.println("Ts is " + Ts);
        return Ts;
    }

    public void identifyCuts(double[] distArray) {
        int columns = distArray.length;
        double tb = this.getTb();
        double ts = this.getTs();
        boolean potentialStartFound = false;
        boolean oneLessThanTsFound = false;
        int Ce = 0 + 1000;
        int Cs = 0 + 1000;
        int FsCandi = 0 + 1000;
        int FeCandi = 0 + 1000;
        for (int p = 0; p < columns; p++) {
            if (distArray[p] > tb) {
                Cs = p + 1000;
                Ce = p + 1000 + 1;
                System.out.println("There is a cut start at " + Cs);
                System.out.println("There is a cut end at " + Ce);
            }
        }
    }

    public ArrayList<Integer> getListGradualTransition(double[] distArray) {
        ArrayList<Integer> gradualTransitionList = new ArrayList<Integer>();
        int columns = distArray.length;
        this.tb = this.getTb();
        this.ts = this.getTs();
        int counter = tor;
        boolean potentialStartFound = false;
        int Ce = 1000;
        int Cs = 1000;
        int FsCandiInitial = 1000;
        int FeCandiInitial = 1000;
        int FeCandi = 1000;
        int FsCandi = 1000;
        double sum = 0;
        System.out.println("Columns is " + columns);
        System.out.println("tor is " + counter);
        for (int p = 0; p <= columns; p++) {
            if (p == columns) {
                if (counter == 0) {
                    FeCandi = FeCandiInitial + p - tor - 1;
                    if (sum > tb && potentialStartFound == true) {
                        System.out.println("Fs+1 is " + FsCandi + " and Found a real end for the Candidate Start at " + FeCandi);
                        gradualTransitionList.add(FsCandi);
                        gradualTransitionList.add(FeCandi);
                    }
                } else {
                    System.out.println("Hit the end of distance Array");
                }
            } else if (distArray[p] > ts && distArray[p] < tb && potentialStartFound == false) {
                FsCandi = FsCandiInitial + p;

                potentialStartFound = true;
                counter = tor;
                sum = sum + distArray[p];
                continue;
            } else if ((distArray[p] > tb) && potentialStartFound == true) {
                if (distArray[p - 1] < ts) { // needs to be a for loop to go back tor times and check if any values are less than ts
                    sum = sum - distArray[p - 1];
                    FeCandi = FeCandiInitial + p - 2;
                } else {
                    FeCandi = FeCandiInitial + p - 1; // not sure if -1 or -2
                }
                if (sum > tb && potentialStartFound == true) {
                    FsCandi = FsCandi + 1;
                    System.out.println("Fs+1 is " + FsCandi + " and Found a real end for the Candidate Start at " + FeCandi);
                    gradualTransitionList.add(FsCandi);
                    gradualTransitionList.add(FeCandi);
                }
                potentialStartFound = false;
                sum = 0;
            } else if (distArray[p] < ts && potentialStartFound == true) {                
                sum = sum + distArray[p];
                counter--;
                if (counter == 0) {                   
                    FeCandi = FeCandiInitial + p - tor;
                    sum = sum - distArray[p];
                    if (distArray[p - 1] < ts) {
                        sum = sum - distArray[p - 1];
                        FeCandi = FeCandi - 1;
                    }
                    if (sum > tb && potentialStartFound == true) {
                        FsCandi = FsCandi + 1;
                        System.out.println("Fs+1 is " + FsCandi + " and Found a real end for the Candidate Start at " + FeCandi);
                        gradualTransitionList.add(FsCandi);
                        gradualTransitionList.add(FeCandi);
                    }
                    potentialStartFound = false;
                    sum = 0;
                }
            } else if (distArray[p] > ts && potentialStartFound == true && counter >= 1) {
                sum = sum + distArray[p];
                if (distArray[p] > ts) {
                    //System.out.println("resetting tor");
                    counter = tor;
                }
            }
        }
        return gradualTransitionList;
    }



   public class Video extends JFrame {

        private JLabel photographLabel = new JLabel();  // new jlabel  
        private JButton[] button; //creates an array of JButtons for images
        private int[] buttonOrder = new int[101]; //creates an array to keep up with the image order
        private int[] selectedImages = new int[99];
        private double[] imageSize = new double[100]; //keeps up with the image sizes
        private GridLayout gridLayout1;
        private GridLayout gridLayout2;
        private GridLayout gridLayout3;
        private GridLayout gridLayout4;
        private JPanel panelBottom1;
        private JPanel panelBottom2;
        private JPanel panelTop;
        private JPanel buttonPanel;
        private double[][] colorCodeIntensityMatrix = new double[100][89];
        //private Map<Double, LinkedList<Integer>> map;
        int picNo = 0; // variable to hold the pic/image index
        int imageCount = 1; //keeps up with the number of images displayed since the first page.
        int selectedImagesIndex;
        int pageNo = 1; // variable to hold the page number
        int iteration = -1;
        JButton previousPage;
        JButton nextPage;
        JCheckBox checkbox; // relevance feedback check box
        JCheckBox iconCheckBox; // check box for each image in the first page
        VideoDecoder vdec;
        ArrayList<Integer> gradualTransitionList = new ArrayList<Integer>();
        //String videoFilename;
        //VideoCapture camera;

        public static void main(String args[]) {
            //new VideoDecoder();
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
            String filePath = "";
            VideoDecoder v = new VideoDecoder(filePath);
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    Video app = new Video(filePath);
                    app.setVisible(true);
                }
            });
        }

        public Video(String videoFilename) {
            vdec = new VideoDecoder(videoFilename);
            vdec.initialize();
            this.gradualTransitionList = new ArrayList<Integer>(
                    Arrays.asList(1866, 1866, 2406, 2421, 2676, 2677, 3200, 3200, 3551, 3569, 3618, 3637, 3765, 3774, 3838, 3849, 3928, 3941, 4042, 4048, 4299, 4299, 4561, 4580, 4607, 4620, 4776, 4789, 4986, 4994));
            System.out.println("Gradual Transition list is:");
            System.out.println(Arrays.toString(this.gradualTransitionList.toArray()));
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setTitle("Video Shot Detection");
            panelBottom1 = new JPanel();
            panelBottom2 = new JPanel();
            panelTop = new JPanel();
            buttonPanel = new JPanel();
            gridLayout1 = new GridLayout(4, 5, 5, 5);
            gridLayout2 = new GridLayout(2, 1, 5, 5);
            gridLayout3 = new GridLayout(1, 2, 5, 5);
            gridLayout4 = new GridLayout(2, 3, 5, 5);
            setLayout(gridLayout2);
            panelBottom1.setLayout(gridLayout1);
            panelBottom2.setLayout(gridLayout1);
            panelTop.setLayout(gridLayout3);
            add(panelTop);
            add(panelBottom1);
            photographLabel.setVerticalTextPosition(JLabel.BOTTOM);
            photographLabel.setHorizontalTextPosition(JLabel.CENTER);
            photographLabel.setHorizontalAlignment(JLabel.CENTER);
            photographLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            buttonPanel.setLayout(gridLayout4);
            panelTop.add(photographLabel);

            panelTop.add(buttonPanel);     
            previousPage = new JButton("Previous Page"); // previous 20 images
            nextPage = new JButton("Next Page"); // next 20 images
            JButton intensity = new JButton("Intensity"); // intensity button to select intensity method
            JButton colorCode = new JButton("Color Code"); // color code button to select color code method
            JButton colorCodeIntensity = new JButton("Color Code and Intensity");
            JButton refresh = new JButton("Refresh"); // refresh button to revert all images to their original positions without having to restart the program
            buttonPanel.add(previousPage);
            buttonPanel.add(nextPage);
            buttonPanel.add(intensity);
            buttonPanel.add(colorCode);
            buttonPanel.add(colorCodeIntensity);
            buttonPanel.add(refresh);

            nextPage.addActionListener(new nextPageHandler()); // setting action for each button using ActionListener
            previousPage.addActionListener(new previousPageHandler());

            refresh.addActionListener(new refreshHandler());

            setSize(1100, 750);       
            setLocationRelativeTo(null);

            button = new JButton[(this.gradualTransitionList.size() / 2) + 1];
            System.out.println("Size of button array is " + button.length);

            Mat frame = new Mat();
            BufferedImage image1;

            for (int i = 0; i < this.gradualTransitionList.size(); i = i + 2) {
                int y = this.gradualTransitionList.get(i);
                System.out.println("will seek to " + y);
                vdec.seek(y);
                vdec.camera.read(frame);
                Imgcodecs.imwrite(y + ".jpg", frame);
                try {           
                    image1 = ImageIO.read(new File(y + ".jpg"));                
                } catch (IOException e) {
                    System.out.println("Error occurred when reading the file."); // printed if an exception is caught
                }          
                ImageIcon icon = new ImageIcon(y + ".jpg");

                if (icon != null) {
                    int m = (i / 2) + 1;
                    System.out.println("i is " + i);
                    System.out.println("m is " + m);
                    button[m] = new JButton(icon); // add the image icon in the button array
                    button[m].addActionListener(new IconButtonHandler(m, icon, this.gradualTransitionList.get(i), this.gradualTransitionList.get(i + 1)));
                    buttonOrder[m] = m; // add the index of each button in the button order array that will be used later on for image preview
                }           
            }
            displayFirstPage(); // display first page method which shows the first 20 image icons
        }

        private void displayFirstPage() {
            imageCount = 1;
            pageNo = 1;
            previousPage.setEnabled(false); // in the firstp age, previous page should be disabled
            nextPage.setEnabled(true); // next page is enabled
            int imageButNo = 0;
            panelBottom1.removeAll(); // refresh the bottom panel
            int u = 0;
            for (int i = 1; i <= 15; i++) {
                imageButNo = buttonOrder[i]; // get the image button number from the buttonOrder array
                System.out.println("Image button number is " + imageButNo);
                panelBottom1.add(button[imageButNo]); // add the button of imageButton number to the bottom panel
                int p = this.gradualTransitionList.get(u);           
                JLabel label1 = new JLabel(p + ".jpg"); // add a label for the button            
                label1.setForeground(Color.BLACK); // set the color to balck
                label1.setFont(new Font("SansSerif", Font.BOLD, 28)); // set the font type and font size
                panelBottom1.add(label1); // add the label to the bottom panel for each new button
                imageCount++; // increment the image count
                u = u + 2;
            }
            panelBottom1.revalidate(); // revalidate and repaint the bottom panel
            panelBottom1.repaint();
        }


        /*This class implements an ActionListener for each iconButton.  When an icon button is clicked, the image on the 
         * the button is added to the photographLabel and the picNo is set to the image number selected and being displayed.
         */
        private class IconButtonHandler implements ActionListener {

            JLabel vidpanel = new JLabel();
            //JFrame jframe = new JFrame("Video");
            int pNo = 0;
            ImageIcon iconUsed;
            ImageIcon imagei;
            Mat frame = new Mat();
            BufferedImage image1;
            int frameStart;
            int frameEnd;

            public BufferedImage Mat2BufferedImage(Mat m) {
                int type = BufferedImage.TYPE_BYTE_GRAY;
                if (m.channels() > 1) {
                    type = BufferedImage.TYPE_3BYTE_BGR;
                }
                int bufferSize = m.channels() * m.cols() * m.rows();
                byte[] b = new byte[bufferSize];
                m.get(0, 0, b); // get all the pixels
                BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);
                final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
                System.arraycopy(b, 0, targetPixels, 0, b.length);
                return image;
            }

            public void displayImage(BufferedImage img)
        {   
            ImageIcon icon = new ImageIcon(img);
            JFrame frame = new JFrame();
            frame.setLayout(new FlowLayout());        
            frame.setSize(img.getWidth(null)+50, img.getHeight(null)+50);     
            JLabel lbl = new JLabel();
            lbl.setIcon(icon);
            frame.add(lbl);
            frame.setVisible(true);
    //        try {
    //                            Thread.sleep(500);
    //                            //jframe.setVisible(true);
    //                        } catch (InterruptedException u) {
    //                            u.printStackTrace();
    //                        }
            //frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
            //frame.setVisible(false); //you can't see me!
            //frame.dispose(); //Destr
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }

            IconButtonHandler(int i, ImageIcon j, int s, int e) {
                pNo = i; // variable to store the image number when clicked
                iconUsed = j;  //sets the icon to the one used in the button
                frameStart = s;
                frameEnd = e;
                //photographLabel.repaint();
                //photographLabel.setVisible(true);

                //panelTop.add(videoLabel);
            }

            public void actionPerformed(ActionEvent e) {
                Mat frame = new Mat();
                //VideoCapture camera = new VideoCapture("C:/MyName/MyPc/Desktop/TheLordOfTheRings.mp4");
                VideoCapture camera = vdec.camera;
                //JFrame jframe = new JFrame("MyTitle");
                //jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                JLabel vidpanel = new JLabel();
                //jframe.setContentPane(vidpanel);
                //jframe.setVisible(true);
                int counter =0;
                while (counter <5) {
                    if (camera.read(frame)) {
                        System.out.println("playing");
                        //image1 = this.Mat2BufferedImage(frame);
                        ImageIcon image = new ImageIcon(this.Mat2BufferedImage(frame));
                        //vidpanel.setIcon(image);
                        //vidpanel.repaint();
                        image1 =this.Mat2BufferedImage(frame);
                        this.displayImage(image1);
                    }
                    counter++;
                }
            }
        }          
    }
...