2017-10-12 379 views
5

我試圖用the BoofCV Android Demo給出的示例使用BoofCV行檢測。爲此,我複製了類並使用Android的Camera API設置了所有內容。 儘管Demo使用風景方向,但我的活動需要使用人像,但設置時相機會向左旋轉90°。當我嘗試設置相機時,沒有任何反應。我用:爲什麼BoofCV不斷地將相機預覽旋轉到左側?

  • Camera.setDisplayOrientation(90)
  • Camera.setParameters("orientation", "portrait")

一段時間,我想通了,這是不相關(在不同的設備和API等級測試)設備後,它不會有什麼關係與相機API以及(因爲我設法得到它在縱向註釋掉VideoProcessor.init()函數)。

嘗試了一段時間我還是想不通,爲什麼VideoProcessor保持圖像向左旋轉後...

這裏是我的VideoProcessor代碼:

public class LineProcessor extends Thread implements VideoProcessing { 

    /** 
    * Lock for reading and writing images with processing and render 
    */ 
    private final Object lockGui = new Object(); 

    /** 
    * Lock used when converting the video stream. 
    */ 
    private final Object lockConvert = new Object(); 

    private Paint mPaint; 
    private ImageType<GrayU8> imageType; 
    private GrayU8 image; 
    private GrayU8 image2; 
    private volatile boolean requestStop = false; 
    private volatile boolean running = false; 
    private int outputWidth; 
    private int outputHeight; 
    private View view; 
    private Thread thread; 

    private DetectLine detector; 
    private FastQueue<LineSegment2D_F32> lines = new FastQueue<LineSegment2D_F32>(LineSegment2D_F32.class,true); 
    private Bitmap bitmap; 
    private byte[] storage; 

    private double scale; 
    private double tranX,tranY; 

    /** 
    * Creates a new Line Processor from a Line Detector 
    * @param detector the Line Detector Segment 
    */ 
    public LineProcessor(DetectLine detector) { 
     this.imageType = ImageType.single(GrayU8.class); 
     this.detector = detector; 

     mPaint = new Paint(); 
     mPaint.setColor(Color.RED); 
     mPaint.setStyle(Paint.Style.STROKE); 
     mPaint.setStrokeWidth(2.0f); 
    } 

    @Override 
    public void init(View view, Camera camera) { 
     synchronized (lockGui) { 
      this.view = view; 

      Camera.Size size = camera.getParameters().getPreviewSize(); 
      outputWidth = size.width; 
      outputHeight = size.height; 
      declareImages(size.width,size.height); 
     } 

     // start the thread for processing 
     running = true; 
     start(); 
    } 



    @Override 
    public void onDraw(Canvas canvas) { 
     synchronized (lockGui) { 
      // the process class could have been swapped 
      if(image == null) 
       return; 

      int w = view.getWidth(); 
      int h = view.getHeight(); 

      // fill the window and center it 
      double scaleX = w/(double)outputWidth; 
      double scaleY = h/(double)outputHeight; 

      scale = Math.min(scaleX,scaleY); 
      tranX = (w-scale*outputWidth)/2; 
      tranY = (h-scale*outputHeight)/2; 

      canvas.translate((float)tranX,(float)tranY); 
      canvas.scale((float)scale,(float)scale); 

      render(canvas, scale); 
     } 
    } 



    @Override 
    public void convertPreview(byte[] bytes, Camera camera) { 
     if(thread == null) 
      return; 

     synchronized (lockConvert) { 
      ConvertUtils.nv21ToGray(bytes, image.width, image.height, image); 

     } 
     // wake up the thread and tell it to do some processing 
     thread.interrupt(); 
    } 

    @Override 
    public void stopProcessing() { 
     if(thread == null) 
      return; 

     requestStop = true; 
     while(running) { 
      // wake the thread up if needed 
      thread.interrupt(); 
      try { 
       Thread.sleep(10); 
      } catch (InterruptedException e) {} 
     } 
    } 

    @Override 
    public void run() { 
     thread = Thread.currentThread(); 
     while(!requestStop) { 
      synchronized (thread) { 
       try { 
        wait(); 
        if(requestStop) 
         break; 
       } catch (InterruptedException e) {} 
      } 

      // swap gray buffers so that convertPreview is modifying the copy which is not in use 
      synchronized (lockConvert) { 
       GrayU8 tmp = image; 
       image = image2; 
       image2 = tmp; 
      } 

      process(image2); 

      view.postInvalidate(); 
     } 
     running = false; 
    } 

    /** 
    * Scaling applied to the drawing canvas 
    */ 
    public double getScale() { 
     return scale; 
    } 

    /** 
    * Translation x applied to the drawing canvas 
    */ 
    public double getTranX() { 
     return tranX; 
    } 

    /** 
    * Translation y applied to the drawing canvas 
    */ 
    public double getTranY() { 
     return tranY; 
    } 


    public void process(GrayU8 gray) { 

     if(detector != null) { 
      List<LineParametric2D_F32> found = detector.detect(gray); 

      synchronized (lockGui) { 
       ConvertUtils.grayToBitmap(gray,bitmap,storage); 
       lines.reset(); 
       for(LineParametric2D_F32 p : found) { 
        LineSegment2D_F32 ls = ConvertUtils.convert(p, gray.width,gray.height); 
        lines.grow().set(ls.a,ls.b); 
       } 
      } 

     } 
    } 

    protected void render(Canvas canvas, double imageToOutput) { 

     canvas.drawBitmap(bitmap,0,0,null); 

     for(LineSegment2D_F32 s : lines.toList()) { 
      canvas.drawLine(s.a.x,s.a.y,s.b.x,s.b.y,mPaint); 
     } 

} 

    protected void declareImages(int width , int height) { 
     image = imageType.createImage(width, height); 
     image2 = imageType.createImage(width, height); 

     bitmap = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888); 
     storage = ConvertUtils.declareStorage(bitmap,storage); 
    } 
} 

的我擴展的類是VideoProcessing.java

有沒有人有這個問題的經驗?

+3

你有沒有嘗試基於相機旋轉旋轉畫布? – noongiya95

+0

是的,它實際上是問題的解決方案...... BoofCV在一個新的畫布上繪製它的東西,無論出於什麼原因旋轉它....我改變了過程函數,我現在要在原始問題中發佈什麼,它的工作原理是完美的精細!非常感謝! – 1resu

回答

2

解決辦法是改變渲染功能如下:

protected void render(Canvas canvas, double imageToOutput) { 

     canvas.rotate(90, 640f/2, 480f/2); 
     canvas.scale(480f/640f, 640f/480f, 640f/2, 480f/2); 
     canvas.drawBitmap(bitmap,0,0,null); 

     for(LineSegment2D_F32 s : lines.toList()) { 
      canvas.drawLine(s.a.x,s.a.y,s.b.x,s.b.y,mPaint); 
     } 
} 

我認爲這是以前沒有的乾淨的方式,但它實際上是唯一的工作方式....