Why does BoofCV constantly rotate Camera Preview to the left?

I am trying to use BoofCV line detection with this example from the BoofCV Android demo . To do this, I copied the classes and installed everything using the Camera API from Android. Although the demo uses Landscape Orientation, my activity should be in the portrait, but when installed, the camera rotates 90 Β° to the left. When I try to install the camera accordingly, nothing happens. I used:

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

After some time, I realized that it was not connected with the device (it is tested on different devices and API levels), and it has nothing to do with the camera’s API (since I managed to get it in the portrait when commenting outside the VideoProcessor.init() function VideoProcessor.init() ).

After trying for a while, I still can not understand why VideoProcessor continues to rotate the image to the left ...

Here is my code for 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(sax,say,sbx,sby,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); } } 

the class I expanded is equal to VideoProcessing.java

Does anyone have any experience with this issue?

+5
source share
1 answer

The solution changes the rendering function to the following:

  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(sax,say,sbx,sby,mPaint); } } 

I thought this was not the same as before, but in fact this is the only working way ....

+2
source

Source: https://habr.com/ru/post/1272564/


All Articles