Android开发之视频监控区域报警设定

最近接到一个来自产品的需求如下:用手在视频画框内画矩形框,矩形框内有物体移动将进行报警,最多三个区域

Android开发之视频监控区域报警设定_第1张图片

刚接到需求脑海瞬间行成了一个解决方案,这得益于我之前对github开源项目的“见多识广”!有事没事多看看一些优秀的开源项目还是很有用的。(每次只能选一个区域上传到服务器,根据次数控制是否支持再次选取)


首先呢感谢开源项目:https://github.com/edmodo/cropper

Android开发之视频监控区域报警设定_第2张图片

我需要如何修改呢?暂且分为以下几个步骤:

  • 获取服务器端原图

  • 根据服务器的宽高比例设定ImageView的宽高

  • 修改开源库矩形框样式级是否隐藏选取框

  • 提供获取矩形四个点的比例值,用于回传到服务器

首先明确一点,服务器的图片按照16:9的约定(16:9的比例我这里是写死的,还可以新增自定义属性来控制),图片的宽高一定大于手机的控件宽高,所以我们需要获取屏幕宽度,按照与服务器约定比例16:9动态设置view宽度(onLayout函数内调用,以防屏幕旋转问题)

 @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

        WindowManager wm = (WindowManager) getContext()
                .getSystemService(Context.WINDOW_SERVICE);
        int width = wm.getDefaultDisplay().getWidth();
        int height = width/16*9;
        setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height));
        super.onLayout(changed, left, top, right, bottom);

        mBitmapRect = getBitmapRect();
        initCropWindow(mBitmapRect);
    }

注意: layoutParmas,這里针对的是我自己项目内父控件编码,如有需要自行修改别完全copy(可以改为通用getLayoutParams..)

如何能保证服务器获取的原图能完全显示到控件里面呢?这里需要使用到ImageView的缩放类型centerInside,如果你还不完全了解scaleType,可以参考下面内容(了解的略过)
内容摘自:

http://blog.csdn.net/hhbgk/article/details/8101676
  • CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示

  • CENTER_CROP / centerCrop 按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)

  • CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽

  • FIT_CENTER / fitCenter 把图片按比例扩大/缩小到View的宽度,居中显示

  • FIT_END / fitEnd 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置

  • FIT_START / fitStart 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置

  • FIT_XY / fitXY 把图片不按比例扩大/缩小到View的大小显示

  • MATRIX / matrix 用矩阵来绘制,动态缩小放大图片来显示。

修改代码如下

  public PrecinctImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
        setScaleType(ScaleType.CENTER_INSIDE);
    }

由于需求有限制选取区域三次,所以新增属性isOpenPrecinct,去掉原有所有自定义属性(都用不到干掉吧,强迫症患者没办法),自定义属性解析后在onDraw 函数做一个开关作用

  "PrecinctImageView">

        "isOpenPrecinct" format="boolean"/>

    

  @Override
  protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        if(isOpenPrecinct){
            drawDarkenedSurroundingArea(canvas);
            drawBorder(canvas);
            drawCorners(canvas);
        }
    }

去掉原有的draw网格线方法,修改四个角的绘制,改为drawCircle

private void drawCorners(@NonNull Canvas canvas) {

        final float left = Edge.LEFT.getCoordinate();
        final float top = Edge.TOP.getCoordinate();
        final float right = Edge.RIGHT.getCoordinate();
        final float bottom = Edge.BOTTOM.getCoordinate();

        final float lateralOffset = (mCornerThickness - mBorderThickness) / 2f;
        final float startOffset = mCornerThickness - (mBorderThickness / 2f);

        canvas.drawCircle(left, top, radioSize, mCornerPaint);

        canvas.drawCircle(right, top, radioSize, mCornerPaint);

        canvas.drawCircle(left, bottom, radioSize, mCornerPaint);

        canvas.drawCircle(right, bottom, radioSize, mCornerPaint);
    }

修改边框圆点样式,通过修改value 下默认值实现


<resources>

    <color name="white_translucent">#AAFFFFFFcolor>
    <color name="black_translucent">#B0000000color>

    <color name="border">#FFB529color>
    <color name="guideline">@color/white_translucentcolor>
    <color name="corner">#FFB529color>
    <color name="surrounding_area">#66000000color>

resources>


<resources>

    <dimen name="border_thickness">1dpdimen>
    <dimen name="corner_thickness">5dpdimen>
    <dimen name="guideline_thickness">1pxdimen>

    <dimen name="target_radius">24dpdimen>
    <dimen name="snap_radius">3dpdimen>
    <dimen name="corner_length">20dpdimen>

resources>

最后一步获取四个点坐标,根据控件的宽高转换为比例值,阅读源码发现Edge类可以为我们直接获取点坐标

 public PointP getPrecinctPointP(){
        PointP pointP = new PointP();

        pointP.setLeftTopX(Edge.LEFT.getCoordinate()/getMeasuredWidth());
        pointP.setLeftTopY(Edge.TOP.getCoordinate() / getMeasuredHeight());

        pointP.setRightTopX(Edge.RIGHT.getCoordinate() / getMeasuredWidth());
        pointP.setRightTopY(Edge.TOP.getCoordinate() / getMeasuredHeight());

        pointP.setLeftBottomX(Edge.LEFT.getCoordinate() / getMeasuredWidth());
        pointP.setLeftBottomY(Edge.BOTTOM.getCoordinate() / getMeasuredHeight());

        pointP.setRightBottomX(Edge.RIGHT.getCoordinate() / getMeasuredWidth());
        pointP.setRightBottomY(Edge.BOTTOM.getCoordinate()/getMeasuredHeight());
        return pointP;
    }

以上修改看上去没有任何问题,但是结果呢总是那么不如人愿!这个开源库getBitmapRect()函数

private RectF getBitmapRect() {

        final Drawable drawable = getDrawable();
        if (drawable == null) {
            return new RectF();
        }
   //*************略************     
 }       

这里获取的src对应的drawable资源,而在某种情况下图片如果比控件宽高小,设置src会导致图片显示不能完全覆盖控件,部分显示纯黑色,如果此时设置为Background,源码里getBitmapRect()获取到的范围值为0,所以这里应该修改代码如下

private RectF getBitmapRect() {

        final Drawable drawable = getBackground();
        if (drawable == null) {
            return new RectF();
        }

"@+id/precinctImageView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/content_padding"
            android:adjustViewBounds="true"
            android:background="@drawable/butterfly"/>

最后附上效果图:

Android开发之视频监控区域报警设定_第3张图片


你可能感兴趣的:(Android,Android音视频学习)