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

来源:互联网 发布:windows ce模拟器 编辑:程序博客网 时间:2024/05/22 10:43

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

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


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

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

  • 获取服务器端原图

  • 根据服务器的宽高比例设定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 函数做一个开关作用

  <declare-styleable name="PrecinctImageView">        <attr name="isOpenPrecinct" format="boolean"/>    </declare-styleable>  @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 下默认值实现

<?xml version="1.0" encoding="utf-8"?><resources>    <color name="white_translucent">#AAFFFFFF</color>    <color name="black_translucent">#B0000000</color>    <color name="border">#FFB529</color>    <color name="guideline">@color/white_translucent</color>    <color name="corner">#FFB529</color>    <color name="surrounding_area">#66000000</color></resources><?xml version="1.0" encoding="utf-8"?><resources>    <dimen name="border_thickness">1dp</dimen>    <dimen name="corner_thickness">5dp</dimen>    <dimen name="guideline_thickness">1px</dimen>    <dimen name="target_radius">24dp</dimen>    <dimen name="snap_radius">3dp</dimen>    <dimen name="corner_length">20dp</dimen></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();        }<idea.analyzesystem.precinct.PrecinctImageView            android:id="@+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"/>

最后附上效果图:


原创粉丝点击