Как обрезать растровые изображения в соответствии с размером пользовательского представления
Попытка создать приложение для обнаружения движения на основе & lt; a href="https://github.com/jkwiecien/android-motion-detector"& gt;& lt;/a> этот проект. Цель состоит в том, чтобы заставить приложение делать снимки при обнаружении движения путем сравнения двух изображений. До этой части приложение работает нормально.
Требование:
Чтобы указать область обнаружения с помощью пользовательского представления. Таким образом, снимки будут сняты только в том случае, если движение будет обнаружено внутри определенной области путем вычисления области обнаружения.
Код проекта: < a href="https://goo.gl/3m9mRU"> & lt; / a>
Что не работает:
Обнаружение движения внутри пользовательского представления не работает. Я считаю, что растровые изображения должны быть обрезаны в соответствии с размером пользовательского представления.
Пожалуйста, помогите мне, объяснив, как это можно сделать, чтобы обнаружение движения происходило в соответствии с размером пользовательского представления. Я новичок в android и пытаюсь самостоятельно учиться,любая помощь приветствуется.
MotionDetectionActivity.java
public class MotionDetectionActivity extends SensorsActivity { private static final String TAG = "MotionDetectionActivity"; private static long mReferenceTime = 0; private static IMotionDetection detector = null; public static MediaPlayer song; public static Vibrator mVibrator; private static SurfaceView preview = null; private static SurfaceHolder previewHolder = null; private static Camera camera = null; private static boolean inPreview = false; private static AreaDetectorView mDetector; private static FrameLayout layoutDetectorArea; static FrameLayout layoutMain; static View mView; private static volatile AtomicBoolean processing = new AtomicBoolean(false); /** * {@inheritDoc} */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.main); mVibrator = (Vibrator)this.getSystemService(VIBRATOR_SERVICE); layoutMain=(FrameLayout)findViewById(R.id.layoutMain); preview = (SurfaceView) findViewById(R.id.preview); previewHolder = preview.getHolder(); previewHolder.addCallback(surfaceCallback); previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mView=layoutMain; mDetector= (AreaDetectorView) findViewById(R.id.viewDetector); layoutDetectorArea=(FrameLayout) findViewById(R.id.layoutDetectArea); ToggleButton toggle = (ToggleButton) findViewById(R.id.simpleToggleButton); toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { // The toggle is enabled } else { // The toggle is disabled } } }); if (Preferences.USE_RGB) { detector = new RgbMotionDetection(); } else if (Preferences.USE_LUMA) { detector = new LumaMotionDetection(); } else { // Using State based (aggregate map) detector = new AggregateLumaMotionDetection(); } } /** * {@inheritDoc} */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); } /**dd: * Song play # 1 * Camera callback * * {@inheritDoc} */ @Override public void onPause() { super.onPause(); if(song!=null && song.isPlaying()) { song.stop();} camera.setPreviewCallback(null); if (inPreview) camera.stopPreview(); inPreview = false; camera.release(); camera = null; } /** * {@inheritDoc} */ @Override public void onResume() { super.onResume(); camera = Camera.open(); } private PreviewCallback previewCallback = new PreviewCallback() { /** * {@inheritDoc} */ @Override public void onPreviewFrame(byte[] data, Camera cam) { if (data == null) return; Camera.Size size = cam.getParameters().getPreviewSize(); if (size == null) return; if (!GlobalData.isPhoneInMotion()) { DetectionThread thread = new DetectionThread(data, size.width, size.height); thread.start(); } } }; private SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() { /** * {@inheritDoc} */ @Override public void surfaceCreated(SurfaceHolder holder) { try { camera.setPreviewDisplay(previewHolder); camera.setPreviewCallback(previewCallback); } catch (Throwable t) { Log.e("Prek", "Exception in setPreviewDisplay()", t); } } /** * {@inheritDoc} */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if(camera != null) { Camera.Parameters parameters = camera.getParameters(); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); Camera.Size size = getBestPreviewSize(width, height, parameters); if (size != null) { parameters.setPreviewSize(size.width, size.height); Log.d(TAG, "Using width=" + size.width + " height=" + size.height); } camera.setParameters(parameters); camera.startPreview(); inPreview = true; } //AreaDetectorView.InitDetectionArea(); } /** * {@inheritDoc} */ @Override public void surfaceDestroyed(SurfaceHolder holder) { // Ignore } }; private static Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) { Camera.Size result = null; for (Camera.Size size : parameters.getSupportedPreviewSizes()) { if (size.width <= width && size.height <= height) { if (result == null) { result = size; } else { int resultArea = result.width * result.height; int newArea = size.width * size.height; if (newArea > resultArea) result = size; } } } return result; } //***************Detection Class******************// private final class DetectionThread extends Thread { private byte[] data; private int width; private int height; public DetectionThread(byte[] data, int width, int height) { this.data = data; this.width = width; this.height = height; } /** * {@inheritDoc} */ @Override public void run() { if (!processing.compareAndSet(false, true)) return; // Log.d(TAG, "BEGIN PROCESSING..."); try { // Previous frame int[] pre = null; if (Preferences.SAVE_PREVIOUS) pre = detector.getPrevious(); // Current frame (with changes) // long bConversion = System.currentTimeMillis(); int[] img = null; if (Preferences.USE_RGB) { img = ImageProcessing.decodeYUV420SPtoRGB(data, width, height); } else { img = ImageProcessing.decodeYUV420SPtoLuma(data, width, height); } // Current frame (without changes) int[] org = null; if (Preferences.SAVE_ORIGINAL && img != null) org = img.clone(); if (img != null && detector.detect(img, width, height)) { // The delay is necessary to avoid taking a picture while in // the // middle of taking another. This problem can causes some // phones // to reboot. long now = System.currentTimeMillis(); if (now > (mReferenceTime + Preferences.PICTURE_DELAY)) { mReferenceTime = now; //mVibrator.vibrate(10); Bitmap previous = null; if (Preferences.SAVE_PREVIOUS && pre != null) { if (Preferences.USE_RGB) previous = ImageProcessing.rgbToBitmap(pre, width, height); else previous = ImageProcessing.lumaToGreyscale(pre, width, height); } Bitmap original = null; if (Preferences.SAVE_ORIGINAL && org != null) { if (Preferences.USE_RGB) original = ImageProcessing.rgbToBitmap(org, width, height); else original = ImageProcessing.lumaToGreyscale(org, width, height); } Bitmap bitmap = null; if (Preferences.SAVE_CHANGES) { if (Preferences.USE_RGB) bitmap = ImageProcessing.rgbToBitmap(img, width, height); else bitmap = ImageProcessing.lumaToGreyscale(img, width, height); } Log.i(TAG, "Saving.. previous=" + previous + " original=" + original + " bitmap=" + bitmap); Looper.prepare(); new SavePhotoTask().execute(previous, original, bitmap); } else { Log.i(TAG, "Not taking picture because not enough time has passed since the creation of the Surface"); } } } catch (Exception e) { e.printStackTrace(); } finally { processing.set(false); } // Log.d(TAG, "END PROCESSING..."); processing.set(false); } }; private static final class SavePhotoTask extends AsyncTask<Bitmap, Integer, Integer> { /** * {@inheritDoc} */ @Override protected Integer doInBackground(Bitmap... data) { for (int i = 0; i < data.length; i++) { Bitmap bitmap = data[i]; String name = String.valueOf(System.currentTimeMillis()); if (bitmap != null) save(name, bitmap); } return 1; } private void save(String name, Bitmap bitmap) { File photo = new File(Environment.getExternalStorageDirectory(), name + ".jpg"); if (photo.exists()) photo.delete(); try { FileOutputStream fos = new FileOutputStream(photo.getPath()); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.close(); } catch (java.io.IOException e) { Log.e("PictureDemo", "Exception in photoCallback", e); } } } }
Prefe.java
public class Prefe extends Application{ ... public static final String PREF_DETECTION_AREA_KEY = "pref_detection_area_key"; } static{ ... DetectionArea = new Rect(1, 1, 1, 1); } }
Что я уже пробовал:
Создал подвижный пользовательский вид, например вид обрезки, размеры которого ("Rect") сохраняются в предпочтении каждый раз при перемещении вида.
В потоке обнаружения я попытался установить ширину и высоту из предпочтения типа
private int width = Prefe.DetectionArea.width(); private int height = Prefe.DetectionArea.height();
Но это не сработало.
AreaDetectorView.java
public class AreaDetectorView extends LinearLayout { public static int Width; public static int Height; private static Paint BoxPaint = null; private static Paint TextPaint = null; private static Paint ArrowPaint = null; private static Path mPath = null; private static Rect mRect = null; private static int lastX, lastY = 0; private static boolean mBoxTouched = false; private static boolean mArrowTouched = false; private static Context mContext; private static int ArrowWidth = 0; private static Paint BoxPaint2 = null; public AreaDetectorView(Context context) { super(context); mContext = context; } //attrs was not there public AreaDetectorView(Context context, AttributeSet attrs) { super(context,attrs); mContext = context; // TODO Auto-generated constructor stub if (!this.getRootView().isInEditMode()) { ArrowWidth =GetDisplayPixel(context, 30); } //InitDetectionArea(); InitMemberVariables(); setWillNotDraw(false); } public static int GetDisplayPixel(Context paramContext, int paramInt) { return (int)(paramInt * paramContext.getResources().getDisplayMetrics().density + 0.5F); } public static void InitMemberVariables() { if (BoxPaint == null) { BoxPaint = new Paint(); BoxPaint.setAntiAlias(true); BoxPaint.setStrokeWidth(2.0f); //BoxPaint.setStyle(Style.STROKE); BoxPaint.setStyle(Style.FILL_AND_STROKE); BoxPaint.setColor(ContextCompat.getColor(mContext, R.color.bwff_60)); } if (ArrowPaint == null) { ArrowPaint = new Paint(); ArrowPaint.setAntiAlias(true); ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.redDD)); ArrowPaint.setStyle(Style.FILL_AND_STROKE); } if (TextPaint == null) { TextPaint = new Paint(); TextPaint.setColor(ContextCompat.getColor(mContext,R.color.yellowL)); TextPaint.setTextSize(16); //txtPaint.setTypeface(lcd); TextPaint.setStyle(Style.FILL_AND_STROKE); } if (mPath == null) { mPath = new Path(); } else { mPath.reset(); } if (mRect == null) { mRect = new Rect(); } if (BoxPaint2 == null) { BoxPaint2 = new Paint(); BoxPaint2.setAntiAlias(true); BoxPaint2.setStrokeWidth(2.0f); //BoxPaint.setStyle(Style.STROKE); BoxPaint2.setStyle(Style.STROKE); BoxPaint2.setColor(ContextCompat.getColor(mContext,R.color.bwff_9e)); } } public static void InitDetectionArea() { try { int w = Prefe.DetectionArea.width(); int h = Prefe.DetectionArea.height(); int x = Prefe.DetectionArea.left; int y = Prefe.DetectionArea.top; // ver 2.6.0 if (Prefe.DetectionArea.left == 1 && Prefe.DetectionArea.top == 1 && Prefe.DetectionArea.right == 1 && Prefe.DetectionArea.bottom == 1) { w = Prefe.DisplayWidth / 4; h = Prefe.DisplayHeight / 3; // ver 2.5.9 w = Width / 4; h = Height / 3; Prefe.DetectorWidth = w; //UtilGeneralHelper.GetDisplayPixel(this, 100); Prefe.DetectorHeight = h; //UtilGeneralHelper.GetDisplayPixel(this, 100); x = (Prefe.DisplayWidth / 2) - (w / 2); y = (Prefe.DisplayHeight / 2) - (h / 2); // ver 2.5.9 x = (Width / 2) - (w / 2); y = (Height / 2) - (h / 2); } //Prefe.DetectionArea = new Rect(x, x, x + Prefe.DetectorWidth, x + Prefe.DetectorHeight); Prefe.DetectionArea = new Rect(x, y, x + w, y + h); Prefe.gDetectionBitmapInt = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()]; Prefe.gDetectionBitmapIntPrev = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()]; } catch (Exception e) { e.printStackTrace(); } } public static void SetDetectionArea(int x, int y, int w, int h) { try { Prefe.DetectionArea = new Rect(x, y, w, h); } catch (Exception e) { e.printStackTrace(); } } private void DrawAreaBox(Canvas canvas) { try { } catch (Exception e) { e.printStackTrace(); } } @Override protected void dispatchDraw(Canvas canvas) { try { if (this.getRootView().isInEditMode()) { super.dispatchDraw(canvas); return; } //canvas.save(Canvas.MATRIX_SAVE_FLAG); //Prefe.DetectionAreaOrient = UtilGeneralHelper.GetDetectRectByOrientation(); canvas.drawColor(0); mPath.reset(); canvas.drawRect(Prefe.DetectionArea, BoxPaint); mPath.moveTo(Prefe.DetectionArea.right - ArrowWidth, Prefe.DetectionArea.bottom); mPath.lineTo(Prefe.DetectionArea.right, Prefe.DetectionArea.bottom - ArrowWidth); mPath.lineTo(Prefe.DetectionArea.right, Prefe.DetectionArea.bottom); mPath.lineTo(Prefe.DetectionArea.right - ArrowWidth, Prefe.DetectionArea.bottom); mPath.close(); canvas.drawPath(mPath, ArrowPaint); mPath.reset(); //canvas.drawRect(Prefe.DetectionAreaOrient, BoxPaint2); //canvas.drawRect(Prefe.DetectionAreaOrientPort, BoxPaint2); TextPaint.setTextSize(16); //TextPaint.setLetterSpacing(2); TextPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff)); TextPaint.getTextBounds(getResources().getString(R.string.str_detectarea), 0, 1, mRect); canvas.drawText(getResources().getString(R.string.str_detectarea), Prefe.DetectionArea.left + 4, Prefe.DetectionArea.top + 4 + mRect.height(), TextPaint); int recH = mRect.height(); TextPaint.setStrokeWidth(1.2f); TextPaint.setTextSize(18); TextPaint.setColor(ContextCompat.getColor(mContext,R.color.redD_9e)); TextPaint.getTextBounds(getResources().getString(R.string.str_dragandmove), 0, 1, mRect); canvas.drawText(getResources().getString(R.string.str_dragandmove), Prefe.DetectionArea.left + 4, Prefe.DetectionArea.top + 20 + mRect.height()*2, TextPaint); TextPaint.getTextBounds(getResources().getString(R.string.str_scalearea), 0, 1, mRect); canvas.drawText(getResources().getString(R.string.str_scalearea), Prefe.DetectionArea.left + 4, Prefe.DetectionArea.top + 36 + mRect.height()*3, TextPaint); super.dispatchDraw(canvas); //canvas.restore(); } catch (Exception e) { e.printStackTrace(); } } @Override protected void onDraw(Canvas canvas) { try { super.onDraw(canvas); invalidate(); } catch (Exception e) { e.printStackTrace(); } finally { } } @Override public boolean onTouchEvent(MotionEvent event) { boolean retValue = true; int X = (int)event.getX(); int Y = (int)event.getY(); //AppMain.txtLoc.setText(String.valueOf(X) + ", " + String.valueOf(Y)); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mBoxTouched = TouchedInBoxArea(X, Y); //AppMain.txtLoc.setText("BoxTouched: " + String.valueOf(mBoxTouched)); if (!mBoxTouched) break; lastX = X; lastY = Y; BoxPaint.setStyle(Style.FILL_AND_STROKE); BoxPaint.setColor(ContextCompat.getColor(mContext,R.color.redD_9e)); mArrowTouched = TouchedInArrow(X, Y); //AppMain.txtLoc.setText("ArrowTouched: " + String.valueOf(mBoxTouched)); if (mArrowTouched) { ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff_9e)); } break; case MotionEvent.ACTION_MOVE: if (!mBoxTouched) break; int moveX = X - lastX; int moveY = Y - lastY; //AppMain.txtLoc.setText("Move X, Y: " + String.valueOf(moveX) + "," + String.valueOf(moveY)); if (!mArrowTouched) { if (Prefe.DetectionArea.left + moveX < 0) { break; } // if (Prefe.DetectionArea.right + moveX > Prefe.gDisplay.getWidth()) { // break; // } // ver 2.5.9 if (Prefe.DetectionArea.right + moveX > Width) { break; } if (Prefe.DetectionArea.top + moveY < 0) { break; } // if (Prefe.DetectionArea.bottom + moveY > Prefe.gDisplay.getHeight()) { // break; // } // ver 2.5.9 if (Prefe.DetectionArea.bottom + moveY > Height) { break; } } if (mArrowTouched) { if ((Prefe.DetectionArea.width() + moveX) < ArrowWidth * 2){ break; } if ((Prefe.DetectionArea.height() + moveY) < ArrowWidth * 2) { break; } Prefe.DetectionArea.right += moveX; Prefe.DetectionArea.bottom += moveY; //Log.i("DBG", "W,H: " + String.valueOf(Prefe.DetectionArea.width()) + "," + String.valueOf(Prefe.DetectionArea.height())); } else { Prefe.DetectionArea.left += moveX; Prefe.DetectionArea.right += moveX; Prefe.DetectionArea.top += moveY; Prefe.DetectionArea.bottom += moveY; } lastX = X; lastY = Y; //AppMain.txtLoc.setText(String.valueOf(Prefe.DetectionArea.left) + ", " + String.valueOf(Prefe.DetectionArea.top)); break; case MotionEvent.ACTION_UP: mBoxTouched = false; mArrowTouched = false; //BoxPaint.setStyle(Style.STROKE); BoxPaint.setStyle(Style.FILL_AND_STROKE); BoxPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff_60)); ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.redDD)); //AppMain.txtLoc.setText(String.valueOf(Prefe.DetectionArea.left) + ", " + String.valueOf(Prefe.DetectionArea.top)); if (Prefe.DetectionArea.left < 0) { Prefe.DetectionArea.left = 0; } // if (Prefe.DetectionArea.right > Prefe.gDisplay.getWidth()) { // Prefe.DetectionArea.right = Prefe.gDisplay.getWidth(); // } // ver 2.5.9 if (Prefe.DetectionArea.right > Width) { Prefe.DetectionArea.right = Width; } if (Prefe.DetectionArea.top < 0) { Prefe.DetectionArea.top = 0; } // if (Prefe.DetectionArea.bottom > Prefe.gDisplay.getHeight()) { // Prefe.DetectionArea.bottom = Prefe.gDisplay.getHeight(); // } if (Prefe.DetectionArea.bottom > Height) { Prefe.DetectionArea.bottom = Height; } Prefe.gDetectionBitmapInt = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()]; Prefe.gDetectionBitmapIntPrev = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()]; //Prefe.gDetectionBitmapInt = null; //Prefe.gDetectionBitmapIntPrev = null; String area = String.valueOf(Prefe.DetectionArea.left) + "," + String.valueOf(Prefe.DetectionArea.top) + "," + String.valueOf(Prefe.DetectionArea.right) + "," + String.valueOf(Prefe.DetectionArea.bottom); // UtilGeneralHelper.SavePreferenceSetting(Prefe.gContext, Prefe.PREF_DETECTION_AREA_KEY, area); //Saving the value SharedPrefsUtils.setStringPreference(mContext.getApplicationContext(), Prefe.PREF_DETECTION_AREA_KEY, area); Log.v("TAG", SharedPrefsUtils.getStringPreference(mContext.getApplicationContext(),Prefe.PREF_DETECTION_AREA_KEY)); break; } invalidate(); return retValue; } private boolean TouchedInBoxArea(int x, int y) { boolean retValue = false; try { if (x > Prefe.DetectionArea.left && x < Prefe.DetectionArea.right) { if (y > Prefe.DetectionArea.top && y < Prefe.DetectionArea.bottom) { retValue = true; } } } catch (Exception e) { e.printStackTrace(); } return retValue; } private boolean TouchedInArrow(int x, int y) { boolean retValue = false; try { if (x > Prefe.DetectionArea.right - ArrowWidth && x < Prefe.DetectionArea.right) { if (y > Prefe.DetectionArea.bottom - ArrowWidth && y < Prefe.DetectionArea.bottom) { retValue = true; } } } catch (Exception e) { e.printStackTrace(); } return retValue; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(width, height); Width = width; Height = height; InitDetectionArea(); } @Override protected void onFinishInflate() { super.onFinishInflate(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub for (int i = 0; i < this.getChildCount()-1; i++){ (this.getChildAt(i)).layout(l, t, r, b); } if (changed) { // check width height if (r != Width || b != Height) { // size does not match } } } }