使用Opencv Java跟踪彩色球

时间:2015-04-30 01:17:33

标签: java opencv image-processing hsv video-tracking

这是我第一次使用opencv。我选择它是因为我有使用JAVA编码的经验。但是在尝试解决编码问题时遇到了一些困难。

  1. 我的第一个问题:
  2. 我想从一个框架中捕捉颜色,这样当我用鼠标点击时它会给我RGB颜色,我可以转换为HSV并发送到我的“inRange方法”,我可以跟踪我从框架中选择的任何颜色。 它不起作用。它给我的颜色与我选择的颜色无关。

    1. 我的第二个问题:
    2. 我想从我的物体中检测轮廓并检测其位置或与相机的距离,但我不确定如何。

      这是我的代码:

      package application;
      
      import java.awt.event.MouseEvent;
      import java.awt.image.BufferedImage;
      import java.io.ByteArrayInputStream;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Timer;
      import java.util.TimerTask;
      
      import javafx.application.Platform;
      import javafx.event.ActionEvent;
      import javafx.event.Event;
      import javafx.event.EventHandler;
      import javafx.event.EventType;
      import javafx.fxml.FXML;
      import javafx.scene.control.Button;
      import javafx.scene.control.Label;
      import javafx.scene.control.Slider;
      import javafx.scene.image.Image;
      import javafx.scene.image.ImageView;
      import javafx.scene.layout.Pane;
      import javafx.scene.paint.Color;
      
      import org.opencv.core.Core;
      import org.opencv.core.CvType;
      import org.opencv.core.Mat;
      import org.opencv.core.MatOfByte;
      import org.opencv.core.MatOfPoint;
      import org.opencv.core.Scalar;
      import org.opencv.core.Size;
      import org.opencv.highgui.Highgui;
      import org.opencv.highgui.VideoCapture;
      import org.opencv.imgproc.Imgproc;
      
      
      public class FxController 
      {
          double h=0,s=0,v=0,tolerance=10;
          @FXML 
          private Button start_b;
          @FXML 
          private ImageView currentFrame,currentFrame2;
          @FXML
          private Slider hSlider,sSlider,vSlider;
          @FXML
          private Label hLabel,sLabel,vLabel;
      
          private Pane rootElement;
          private Timer timer;
          private VideoCapture capture = new VideoCapture();
          private EventHandler handler;
          private  int red,green,bleu;
          private double alpha ;
      
          //private float hsb[];
           @FXML 
          protected void startCamera(ActionEvent event)
          {
              if(this.rootElement!=null)//savoir wache main class est accessible 
              {
                  final ImageView frameView = currentFrame;//prendre l'objet ImageView pour montre le streaming
                  final ImageView frameView2 = currentFrame2;
                  /*handler = new EventHandler(){//clic dial la souris wesst l'image
      
      
                      @Override
                      public void handle(Event e) {
                          System.out.println("YOOOOO"+e.getEventType());
      
      
                      }
                  };*/
                  frameView.setOnMouseClicked(Event->{Mat m= new Mat();
                                                          byte[] pixel=new byte[4];
                                                          //int [] rgb = new int[3];
                                                          float[] hsv = new float[3];
                                                          //Imgproc.cvtColor(grabMat(0),m,CvType.CV_8UC1);
                                                          grabMat(0).convertTo(m, CvType.CV_8UC3);
                                                          m.get((int)Event.getX(),(int)Event.getY(),pixel);
                                                          /*alpha=(pixel[0] >> 24) & 0xff;
                                                          red=(pixel[1] >> 16) & 0xff;
                                                          green=(pixel[2] >> 8) & 0xff;
                                                          bleu=(pixel[3]) & 0xff;*/
                                                          alpha=pixel[0] & 0xff;
                                                          red=pixel[1] & 0xff;
                                                          green=pixel[2] & 0xff;//fuuuuuuuuuuuuuuuuuuuuuck 
                                                          bleu=pixel[3] & 0xff;
                                                          hsv=java.awt.Color.RGBtoHSB(red,green,bleu, null);
                                                          System.out.println("alpha= "+alpha+"---red= "+red+"---bleu= "+bleu+"---green= "+green);
                                                          h= hsv[0];
                                                          s=hsv[1];
                                                          v=hsv[2];
                                                          System.out.println("h= "+h+"---s= "+s+"---v= "+v);
                                                          //Event.getX();//x du pixel ou la souris berkat
                                                          //Event.getY();
                                                          //BufferedImage.setRGB(Event.getX(),Event.getY(), Color.getRGB());
                                                          });
      
                  if(!this.capture.isOpened())//voir est c que la capture stream est ouverte
                  {
                      this.capture.open(0);//commence la capture video 
                      //prendre le fram chaque 33 ms(30 frames/sec)
                      TimerTask FrameGrabber = new TimerTask(){
                          @Override 
                          public void run()
                          {
                              Image tmp = grabFrame(Imgproc.COLOR_RGB2RGBA);//imageRGB
                              //Image tmp2 = grabFrame(Imgproc.COLOR_RGB2HSV);
                              Image tmp3 = newColorDetection(grabMat(Imgproc.COLOR_BGR2HSV));
                              Platform.runLater(new Runnable(){
                                  @Override 
                                  public void run()
                                  {
                                      frameView.setImage(tmp);
      
                                      frameView2.setImage(tmp3);
                                  }
                              });
                          }
                      };
                      this.timer = new Timer();
                      this.timer.schedule(FrameGrabber,0,33);
                      this.start_b.setText("Stop Camera");
                      }
                  else 
                  {
                      this.start_b.setText("Start Camera");
                      //arrete le timer
                      if(this.timer!=null)
                      {
                          this.timer.cancel();
                          this.timer = null;
                      }
                      //realease camera
                      this.capture.release();
                      //efface le contenaire d'image 
                      frameView.setImage(null);
                      frameView2.setImage(null);
                  }
      
              }
          }
      
      
      
          private Image grabFrame(int img)
          {
              Image imageToShow =null;//init
              Mat frame = new Mat();// cree une matrice
              //checker si la capture est ouverte
              if(this.capture.isOpened())
              {
                  try{
                      this.capture.read(frame);//lire le frame courant
                      //test si le frame est vide
                      if(!frame.empty())
                      {
                          //convertire l'image au gris
                          Imgproc.cvtColor(frame, frame,img);
                          //convertir la Mat (objet) a Image (javaFx)
                          imageToShow = mat2Image(frame);
                      }
                  }catch(Exception e){System.err.println("ERROR: "+e.getMessage());}
              }
              return imageToShow;
      
          }
          private Mat grabMat(int img)
          {
              Image imageToShow =null;//init
              Mat frame = new Mat();// cree une matrice
              //checker si la capture est ouverte
              if(this.capture.isOpened())
              {
                  try{
                      this.capture.read(frame);//lire le frame courant
                      //test si le frame est vide
                      if(!frame.empty())
                      {
                          //convertire l'image au gris
                          Imgproc.cvtColor(frame, frame,img);
                          //convertir la Mat (objet) a Image (javaFx)
      
                      }
                  }catch(Exception e){System.err.println("ERROR: "+e.getMessage());}
              }
      
              return frame;
      
          }
      
      
          private Image matToThresHolded(Mat frame)
          {   Image thresHoldedImg =null;
              Mat dFrame = new Mat();
              Imgproc.threshold(frame, dFrame, 127, 255,Imgproc.THRESH_TOZERO);
              thresHoldedImg=mat2Image(dFrame);
              return thresHoldedImg;
          }
          private Image mat2Image (Mat frame)
          {   //cree un buffer temporaire
              MatOfByte buffer = new MatOfByte();
              //encode le frame dans le buffer
              Highgui.imencode(".png",frame, buffer);
              //construire et retourne une image cree depuis l'image encode dans le buffer
              return new Image(new ByteArrayInputStream(buffer.toArray()));
      
          }
          public void setRootElement(Pane root)
          {
              this.rootElement = root;
          }
          public Image colorDetection(Mat hsvImage)
          {
              Image imageToShow=null;
              Mat threshedImg =new Mat();
              //Scalar hsvMin=new Scalar(106,60,90,0);//red
              //Scalar hsvMax=new Scalar(124,255,255,0);//red
              Scalar hsvMin=new Scalar(100,150,100);//bleu
              Scalar hsvMax=new Scalar(140,255,255);//bleu
          Core.inRange(hsvImage,hsvMin, hsvMax, threshedImg);
          imageToShow = mat2Image(threshedImg);
           return imageToShow;
          }
          public  Image newColorDetection(Mat hsv)
          {
      
              Image imageToShow=null;
              Mat threshedImg =new Mat(); 
              Mat threshedImg2 =new Mat();    
              Scalar hsvMin = new Scalar(0, 50, 50, 0);//red
              Scalar hsvMax = new Scalar(6, 255, 255, 0);//red
              Scalar hsvMin2 = new Scalar(175, 50, 50, 0);//red
              Scalar hsvMax2 = new Scalar(179, 255, 255, 0);//red
              //Scalar hsvMin=new Scalar(100,150,100);//bleu
              //Scalar hsvMax=new Scalar(140,255,255);//bleu
              //Scalar hsvMin=new Scalar(h-tolerance-1, s-tolerance, 0);//default
              //Scalar hsvMax=new Scalar(h+tolerance-1, s+tolerance,255);//default
           Core.inRange(hsv,hsvMin,hsvMax,threshedImg);
           Core.inRange(hsv, hsvMin2, hsvMax2, threshedImg2);
           Core.bitwise_or(threshedImg, threshedImg2, threshedImg);
          // dilate et erosion pour renforce l'image et supprime les pixels lmcheyrin 
          Mat dilate = Imgproc.getStructuringElement(Imgproc.MORPH_DILATE, new Size(3, 3));
              Imgproc.dilate(threshedImg, threshedImg, dilate);//dilate   
          Mat erode = Imgproc.getStructuringElement(Imgproc.MORPH_ERODE, new Size(3, 3));
              Imgproc.erode(threshedImg, threshedImg, erode);
              List<MatOfPoint> contours = new ArrayList<MatOfPoint>();    
              Imgproc.findContours(threshedImg, contours, new Mat(), Imgproc.RETR_LIST,Imgproc.CHAIN_APPROX_SIMPLE);
              imageToShow = mat2Image(threshedImg);
           return imageToShow;
      
          }
      }
      

      我的主要

      package application;
      
      import org.opencv.core.Core;
      
      import javafx.application.Application;
      import javafx.stage.Stage;
      import javafx.scene.Scene;
      import javafx.scene.layout.BorderPane;
      import javafx.fxml.FXMLLoader;
      
      public class Main extends Application {
          @Override
          public void start(Stage primaryStage) {
              try {
                  FXMLLoader loader = new FXMLLoader(getClass().getResource("FristProjectFX.fxml"));
                  BorderPane root = (BorderPane)loader.load();
                  Scene scene = new Scene(root);
                  scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
                  primaryStage.setTitle("JavaFx YO!");
                  primaryStage.setAlwaysOnTop(true);
                  primaryStage.setScene(scene);
                  primaryStage.show();//show GUI
                  FxController controller = loader.getController();
                  controller.setRootElement(root);
              } catch(Exception e) {
                  e.printStackTrace();
              }
          }
      
          public static void main(String[] args) {
              System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
              launch(args);
          }
      }
      

      这就是我得到的 enter image description here

      就像你在下面的图片中看到的那样,当我点击红色区域时,我没有得到红色代码甚至是其他颜色。

      我的期望是

      enter image description here

      就像你在图片上看到的那样,我可以抓住球和距离!

1 个答案:

答案 0 :(得分:2)

我找到了第一个问题的解决方案

frameView.setOnMouseClicked(Event->{Mat m= new Mat();
                                                double[] pixel=new double[3];

                                                float[] hsv = new float[3];

                                                grabMat(0).convertTo(m, CvType.CV_8U);
                                                Imgproc.cvtColor(m, m, Imgproc.COLOR_BGR2RGB, 3);

                                                pixel=m.get((int)Event.getX(),(int)Event.getY());

                                                red=pixel[0];
                                                green=pixel[1];
                                                bleu=pixel[2];
                                            System.out.println("X= "+Event.getX()+"Y="+Event.getY()+"---red= "+red+"---bleu= "+bleu+"---green= "+green);
                                            hsv=java.awt.Color.RGBtoHSB((int)red,(int)green,(int)bleu, null);
                                            h= hsv[0];
                                            s=hsv[1];
                                            v=hsv[2];
                                                System.out.println("h= "+h+"---s= "+s+"---v= "+v);


                                                });