数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

「深度学习福利」大神带你进阶工程师,立即查看>>>
Android 的音视频入门学习,首先了解一下绘制图片。在 Android 平台绘制一张图片,使用至少 3 种不同的 API,ImageView,SurfaceView,自定义 View作绘制图片。下面我以SurfaceView作重点来讲,为什么不用其他的来作例子,分析完SurfaceView就是知道为什么要用SurfaceView作例子。
SurfaceView
我们以下面几个点来了解SurfaceView SurfaceView 有那些相关类。 SurfaceView 有那些特点。 如何使用SurfaceView呢。 SurfaceView的优缺。 SurfaceView 在视频开发中应用在那里。
SurfaceView 其实是继承了View ,但与View又有一些区别,View是通过 onDraw(Canvas canvas)方法中的Canvas去绘制自身显示有界面上,而SurfaceView则不需要onDraw方法,有人会有些疑问,如果SurfaceView不需要实现onDraw方法怎么去绘制自身呢?其实View是在UI线程中绘制的,SurfaceView是在子线程中绘制的(即在一个子线程中对自己进行绘制)。在子线程中绘制怎么拿到canvas呢?下面我们去了解SurfaceView 有那些相关类。
SurfaceView 有那些相关类。
有三个重要的类,分别如下: Surface SurfaceHolder SurfaceView
Surface 我们看看Surface的源码 /** * Handle onto a raw buffer that is being managed by the screen compositor. * *

A Surface is generally created by or from a consumer of image buffers (such as a * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL}, * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw * into.

* *

Note: A Surface acts like a * {@link java.lang.ref.WeakReference weak reference} to the consumer it is associated with. By * itself it will not keep its parent consumer from being reclaimed.

*/ public class Surface implements Parcelable { private static final String TAG = "Surface"; private static native long nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture) throws OutOfResourcesException; private static native long nativeCreateFromSurfaceControl(long surfaceControlNativeObject); private static native long nativeLockCanvas(long nativeObject, Canvas canvas, Rect dirty) throws OutOfResourcesException; private static native void nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas); private static native void nativeRelease(long nativeObject); private static native boolean nativeIsValid(long nativeObject); ....... /** * Create Surface from a {@link SurfaceTexture}. * * Images drawn to the Surface will be made available to the {@link * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link * SurfaceTexture#updateTexImage}. * * @param surfaceTexture The {@link SurfaceTexture} that is updated by this * Surface. * @throws OutOfResourcesException if the surface could not be created. */ public Surface(SurfaceTexture surfaceTexture) { if (surfaceTexture == null) { throw new IllegalArgumentException("surfaceTexture must not be null"); } mIsSingleBuffered = surfaceTexture.isSingleBuffered(); synchronized (mLock) { mName = surfaceTexture.toString(); setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture)); } } /* called from android_view_Surface_createFromIGraphicBufferProducer() */ private Surface(long nativeObject) { synchronized (mLock) { setNativeObjectLocked(nativeObject); } } ........ }
也不难看出,其实Surface就充当着Model层,也是一个原始数据的缓冲区,表面通常是由图像缓冲区的使用者创建的。
SurfaceHolder 看看SurfaceHolder的源码 /** * Abstract interface to someone holding a display surface. Allows you to * control the surface size and format, edit the pixels in the surface, and * monitor changes to the surface. This interface is typically available * through the {@link SurfaceView} class. * *

When using this interface from a thread other than the one running * its {@link SurfaceView}, you will want to carefully read the * methods * {@link #lockCanvas} and {@link Callback#surfaceCreated Callback.surfaceCreated()}. */ public interface SurfaceHolder { /** @deprecated this is ignored, this value is set automatically when needed. */ @Deprecated public static final int SURFACE_TYPE_NORMAL = 0; /** @deprecated this is ignored, this value is set automatically when needed. */ @Deprecated public static final int SURFACE_TYPE_HARDWARE = 1; /** @deprecated this is ignored, this value is set automatically when needed. */ @Deprecated public static final int SURFACE_TYPE_GPU = 2; /** @deprecated this is ignored, this value is set automatically when needed. */ @Deprecated public static final int SURFACE_TYPE_PUSH_BUFFERS = 3; /** * Exception that is thrown from {@link #lockCanvas} when called on a Surface * whose type is SURFACE_TYPE_PUSH_BUFFERS. */ public static class BadSurfaceTypeException extends RuntimeException { public BadSurfaceTypeException() { } public BadSurfaceTypeException(String name) { super(name); } } /** * A client may implement this interface to receive information about * changes to the surface. When used with a {@link SurfaceView}, the * Surface being held is only available between calls to * {@link #surfaceCreated(SurfaceHolder)} and * {@link #surfaceDestroyed(SurfaceHolder)}. The Callback is set with * {@link SurfaceHolder#addCallback SurfaceHolder.addCallback} method. */ public interface Callback { /** * This is called immediately after the surface is first created. * Implementations of this should start up whatever rendering code * they desire. Note that only one thread can ever draw into * a {@link Surface}, so you should not draw into the Surface here * if your normal rendering will be in another thread. * * @param holder The SurfaceHolder whose surface is being created. */ public void surfaceCreated(SurfaceHolder holder); /** * This is called immediately after any structural changes (format or * size) have been made to the surface. You should at this point update * the imagery in the surface. This method is always called at least * once, after {@link #surfaceCreated}. * * @param holder The SurfaceHolder whose surface has changed. * @param format The new PixelFormat of the surface. * @param width The new width of the surface. * @param height The new height of the surface. */ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height); /** * This is called immediately before a surface is being destroyed. After * returning from this call, you should no longer try to access this * surface. If you have a rendering thread that directly accesses * the surface, you must ensure that thread is no longer touching the * Surface before returning from this function. * * @param holder The SurfaceHolder whose surface is being destroyed. */ public void surfaceDestroyed(SurfaceHolder holder); } /** * Additional callbacks that can be received for {@link Callback}. */ public interface Callback2 extends Callback { /** * Called when the application needs to redraw the content of its * surface, after it is resized or for some other reason. By not * returning from here until the redraw is complete, you can ensure that * the user will not see your surface in a bad state (at its new * size before it has been correctly drawn that way). This will * typically be preceeded by a call to {@link #surfaceChanged}. * * @param holder The SurfaceHolder whose surface has changed. */ public void surfaceRedrawNeeded(SurfaceHolder holder); } /** * Add a Callback interface for this holder. There can several Callback * interfaces associated with a holder. * * @param callback The new Callback interface. */ public void addCallback(Callback callback); ......... }
从源码有可以看出,SurfaceHolder是以接口的形式给持有显示表面使用,允许你控制表面尺寸和格式,编辑表面的像素。监视对表面的更改。我们可以理解为SurfaceHolder充当控制层,管理Surface的生命周期,让SurfaceView来绘制Surface的数据。
SurfaceView
SurfaceView就是视图层,SurfaceView 中包含一个专门用于绘制的Surface ,Surface中包含了一个Canvas。如果细心的一点,也不难发现Surface、SurfaceHolder、SurfaceView其实就是一个MVC模式。
那么问题不了,那么如何获取到Canvas? 在SurfaceView中有一个getHolder() -> SurfaceHolder。那么Holder包含了Canvas(Canvas+管理SurfaceView的生命周期)。所以Canvas = holder.lockCanvas()。调用生命周期的holder.addCallback(Callback callback)。 SurfaceView的生命周期管理有三个方法: SurfaceCreated SurfaceChanged SurfaceDestoryed
如何使用SurfaceView呢?
1、获取SurfaceHolder对象,其是SurfaceView的内部类。 监听Surface生命周期。 只有当native层的Surface创建完毕之后,才可以调用lockCanvas(),否则失败。 holder.Callback。
2、调用holder.lockCanvas()。 3、绘制 4、调用SurfaceHolder.unlockCanvasAndPost,将绘制内容post到Surface中
注意:第3、4、5步是在子线程中执行的。
SurfaceView的特点有那些
具有独立的绘图表面Surface。
需要在宿主窗口上挖一个洞来显示自己,z轴比普通的window要小。
它的UI绘制可以在独立的线程中进行,这样就可以进行复杂的UI绘制,并且不会影响应用程序的主线程响应用户输入。
SurfaceView的优缺点
优点 在一个子线程中对自己进行绘制,避免造成UI线程阻塞。 高效复杂的UI效果。 独立Surface,独立的Window。 使用双缓冲机制,播放视频时画面更流畅。
缺点 每次绘制都会优先绘制黑色背景,更新不及时会出现黑边现象。 Surface不在View hierachy中,它的显示也不受View的属性控制,平移,缩放等变换。
SurfaceView的基本知道了解得差不多了,那么我们写一个SurfaceView绘制图片的一个公共View的实现。 public class CommonSurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable { private SurfaceHolder mHolder; private Canvas mCanvas; //用于绘制的线程 private Thread mThread; //线程状态的标记(线程的控制开关) private boolean isRunning; public CommonSurfaceView(Context context) { this(context,null); } public CommonSurfaceView(Context context, AttributeSet attrs) { this(context, attrs,0); } public CommonSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //初始化 mHolder = getHolder(); mHolder.addCallback(this);//管理生命周期 //获取焦点 setFocusable(true); setFocusableInTouchMode(true); //设置常量 setKeepScreenOn(true); } @Override public void surfaceCreated(SurfaceHolder holder) { isRunning = true; mThread = new Thread(this); mThread.start();//开启线程 } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { isRunning = false; } @Override public void run() { //不断地进行绘制 while (isRunning){ draw(); } } private void draw() { //为什么要try catch 因为当view在主界面时有可能按Home键或Back键时回到界面,Surface被销毁了。 //这时有可能已经进入到draw() ,这时候获取的mCanvas可能为null。 // 还有一种可能,就是界面被销毁的,我们的线程还没有销毁,mCanvas可能为null。 try{ //获取Canvas mCanvas = mHolder.lockCanvas(); if(mCanvas !=null){ //do something } }catch (Exception e){ e.printStackTrace(); }finally { if(mCanvas !=null){ //释放Canvas mHolder.unlockCanvasAndPost(mCanvas); } } } }
总结一下有那些问题、疑虑 不绘制任何东西,SurfaceView显示的是黑色? SurfaceView 能绘制什么东西? SurfaceVeiw双缓冲区 SurfaceView 和 SurfaceHolder 怎么交互? SurfaceHolder与Surface的交互 SurfaceView 怎么进行旋转,透明操作的? 一般视频播放器可以横竖屏切换,是如何实现的? SurfaceView 和普通的View的区别? SurfaceView 挖洞原理 SurfaceView 生命周期 横屏录制横屏播放,竖屏录制竖屏播放
那么我们来解答一下上面的一些疑虑和问题,就浅析一下,有做得不好的请多多指出,谢谢。
不绘制任何东西,SurfaceView显示的是黑色?
每次更新视图时都会先将背景绘制成黑色。所以在移动或者缩放过程,会更新不及时时就会看黑边。 @Override public void draw(Canvas canvas) { if (mDrawFinished && !isAboveParent()) { // draw() is not called when SKIP_DRAW is set if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) { // punch a whole in the view-hierarchy below us canvas.drawColor(0, PorterDuff.Mode.CLEAR); } } super.draw(canvas); } //这句话表示PorterDuff.Mode.CLEAR会将像素设置为0,也就是黑色 //Destination pixels covered by the source are cleared to 0. public enum Mode { // these value must match their native equivalents. See SkXfermode.h /** *

* *

Destination pixels covered by the source are cleared to 0.
*

*

\(\alpha_{out} = 0\)

*

\(C_{out} = 0\)

*/ CLEAR (0), }
SurfaceView 能绘制什么东西?
从下面代码可以看到,SurfaceView 的绘制也是使用 Canvas 进行绘制的,绘制应该跟普通的 View 绘制差不多 /** * 绘制 */ private void draw() { if (radius > getWidth()) { return; } Canvas canvas = mHolder.lockCanvas(); if (canvas != null) { canvas.drawCircle(300, 300, radius += 10, mPaint); mHolder.unlockCanvasAndPost(canvas); } }
SurfaceVeiw双缓冲区
双缓冲:在运用时可以理解为:SurfaceView在更新视图时用到了两张 Canvas,一张 frontCanvas 和一张 backCanvas ,每次实际显示的是 frontCanvas ,backCanvas 存储的是上一次更改前的视图。当你在播放这一帧的时候,它已经提前帮你加载好后面一帧了,所以播放起视频很流畅。 当使用lockCanvas()获取画布时,得到的实际上是backCanvas 而不是正在显示的 frontCanvas ,之后你在获取到的 backCanvas 上绘制新视图,再 unlockCanvasAndPost(canvas)此视图,那么上传的这张 canvas 将替换原来的 frontCanvas 作为新的frontCanvas ,原来的 frontCanvas 将切换到后台作为 backCanvas 。例如,如果你已经先后两次绘制了视图A和B,那么你再调用 lockCanvas()获取视图,获得的将是A而不是正在显示的B,之后你将重绘的 A 视图上传,那么 A 将取代 B 作为新的 frontCanvas 显示在SurfaceView 上,原来的B则转换为backCanvas。
相当与多个线程,交替解析和渲染每一帧视频数据。 surfaceholder.lockCanvas--surfaceholder.unlockCanvasAndPost
SurfaceView 和 SurfaceHolder 怎么交互?
SurfaceHolder 是 SurfaceView 内部类,可以通过 SurfaceView.getHolder() 即可获取对应的 SurfaceHolder 对象。
通过getHolder() 就可以将SurfaceHolder,然后将其传递给MediaPlayer或者Camera 显示出来。实际上就是通过SurfaceHolder去控制SurfaceView的显示。 public SurfaceHolder getHolder() { return mSurfaceHolder; }
SurfaceHolder与Surface的交互
SurfaceHolder 是一个接口,它具体的实现在 SurfaceView 中定义的一个内部类。对于 SurfaceHolder 的操作,实际上是操作Surface 的相关接口。
因为 Surface 会牵扯到 native 层的 Surface ,只有 Native 层的 Surface 创建成功之后,我们才能真正开始去绘制我们的视图。
那么如何去捕获到这个 Surface 的创建生命周期呢?
注册 SurfaceHolder.Callback 接口,监听这个接口的回调:
surfaceCreated 播放视频
surfaceDestroy 停止视频播放 Canvas canvas = mHolder.lockCanvas(); if (canvas != null) { canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher, null), 0, 0, mPaint); mHolder.unlockCanvasAndPost(canvas); }
mHolder.lockCanvas(); 实际获取的是 Surface 中的 Canvas。 @Override public Canvas lockCanvas() { return internalLockCanvas(null); } private final Canvas internalLockCanvas(Rect dirty) { mSurfaceLock.lock(); Canvas c = null; if (!mDrawingStopped && mWindow != null) { try { //实际调用的是 surface.lockCancas() c = mSurface.lockCanvas(dirty); } catch (Exception e) { Log.e(LOG_TAG, "Exception locking surface", e); } } ... return null; }
canvas.drawXXX(); 在 Canvas 中绘制内容。
mHolder.unlockCanvasAndPost(canvas);将 绘制在 Canvas 中的内容刷新到 Surface 中。 //将 backcanvas 中的内容刷新到 surface 中并且释放这个 canvas @Override public void unlockCanvasAndPost(Canvas canvas) { mSurface.unlockCanvasAndPost(canvas); mSurfaceLock.unlock(); }
SurfaceView 怎么进行旋转,透明操作的? 普通View旋转后,View的内容也跟着同步做了旋转. SurfaceView在旋转之后,其显示内容并没有跟着一起旋转.
比喻:这就好比在墙上开了一个窗(Surface),通过窗口可以看外面的花花世界,但窗口无论怎样变化,窗外面的世界是不会跟着窗口一同变化。
一般视频播放器可以横竖屏切换,是如何实现的? 在 Activity 中覆写 onConfigurationChanged 方法就可以。根据横竖屏切换,修改 SurfaceView 的 Parameter 的宽高参数即可。 android:configChanges="orientation|keyboardHidden|screenSize" @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { //变成横屏了 } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { //变成竖屏了 } }
SurfaceView 挖洞原理
挖洞原理了解之后再补上吧
SurfaceView 和普通的View的区别? surfaceView是在一个新起的单独线程中可以重新绘制画面。 View必须在UI的主线程中更新画面。 那么在UI的主线程中更新画面可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。 当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。
SurfaceView 生命周期
使用:双缓冲 导致:需要更多的内存开销 为了节约系统内存开销:
SurfaceView 可见时 -> 创建 SurfaceHolder SurfaecView 不可见时 -> 摧毁 SurfaceHolder
1、程序打开 Activity 调用顺序:onCreate()->onStart()->onResume() SurfaceView 调用顺序: surfaceCreated()->surfaceChanged()
2、程序关闭(按 BACK 键) Activity 调用顺序:onPause()->onStop()->onDestory() SurfaceView 调用顺序: surfaceDestroyed()
3、程序切到后台(按 HOME 键) Activity 调用顺序:onPause()->onStop() SurfaceView 调用顺序: surfaceDestroyed()
4、程序切到前台 Activity 调用顺序: onRestart()->onStart()->onResume() SurfaceView 调用顺序: surfaceChanged()->surfaceCreated()
5、屏幕锁定(挂断键或锁定屏幕) Activity 调用顺序: onPause() SurfaceView 什么方法都不调用
6、屏幕解锁 Activity 调用顺序: onResume() SurfaceView 什么方法都不调用
横屏录制横屏播放,竖屏录制竖屏播放 通过以下方法可以获取到视频的宽高,根据视频的宽高就可以知道该视频是横屏还是竖屏录制的。 public void onVideoSizeChanged(MediaPlayer mp, int width, int height)
横屏判断:width>height 旋转屏幕:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
竖屏录制:height>width 旋转屏幕:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); mediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() { @Override public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { Log.e(TAG, "onVideoSizeChanged:WIDTH>>" + width); Log.e(TAG, "onVideoSizeChanged:HEIGHT>>" + height); if (width > height) { //横屏录制 if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } } else { //竖屏录制 if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } } } });
View的绘制要知道的知识 View的绘制其实是在UI线程(实现onCanvas方法进行绘制)。如果进行绘制高效复杂的UI,最好不用自定义View。要用SurfaceView进行绘制。
View的绘画三要素 Canvas (画布,绘制BitMap操作) Paint (绘制的画笔Paint,颜色、样式) Path (路径)
一、Canvas 如果直接extends View 可以重写onDraw(Canvas canvas)方法,直接用里面的canvas进行绘制。 可以直接利用Activity的绘制机制,用lockCanvas()方法来获得当前的Activity的Canvas。 在SurfaceView中,同2可以利用SurfaceHolder的对象的lockCanvas()方法来Canvas。
二、Paint
直接通过new关键字来实例化,然后通过Paint对象来对画笔进行相应的设置: 如: 1.1 去锯齿setAntiAlia(true) 1.2 去抖动setDither(true) 1.3 设置图层混合模式setXfermode(Xfermode,xfermode)
三、 Path 1、Path路径 直接用new来实例化 2、通过path对象设置想要画图的轨迹或路线,如:矩形 、三角形 、圆、曲线等
实现一个自定义View,代码如下: //自定义绘图类 public class BallView extends View { private Paint paint; //定义画笔 private float cx = 150; //圆点默认X坐标 private float cy = 250; //圆点默认Y坐标 private int radius = 60; // 半径 //定义颜色数组 private int colorArray[] = {Color.BLACK,Color.BLACK,Color.GREEN,Color.YELLOW, Color.RED}; private int paintColor = colorArray[0]; //定义画笔默认颜色 private int screenW; //屏幕宽度 private int screenH; //屏幕高度 public BallView(Context context,int screenW,int screenH) { super(context); this.screenW=screenW; this.screenH=screenH; //初始化画笔 initPaint(); } private void initPaint(){ paint = new Paint(); //设置消除锯齿 paint.setAntiAlias(true); //设置画笔颜色 paint.setColor(paintColor); } //重写onDraw方法实现绘图操作 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //将屏幕设置为白色 canvas.drawColor(Color.WHITE); //修正圆点坐标 revise(); //随机设置画笔颜色 setPaintRandomColor(); //绘制小圆作为小球 canvas.drawCircle(cx, cy, radius, paint); } //为画笔设置随机颜色 private void setPaintRandomColor(){ Random rand = new Random(); int randomIndex = rand.nextInt(colorArray.length); paint.setColor(colorArray[randomIndex]); } //修正圆点坐标 private void revise(){ if(cx <= radius){ cx = radius; }else if(cx >= (screenW-radius)){//防止出边界 cx = screenW-radius; } if(cy <= radius){ cy = radius; }else if(cy >= (screenH-radius)){//防止出边界 cy = screenH-radius; } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 按下 cx = (int) event.getX(); cy = (int) event.getY(); // 通知重绘 postInvalidate(); //该方法会调用onDraw方法,重新绘图 break; case MotionEvent.ACTION_MOVE: // 移动 cx = (int) event.getX(); cy = (int) event.getY(); // 通知重绘 postInvalidate(); break; case MotionEvent.ACTION_UP: // 抬起 cx = (int) event.getX(); cy = (int) event.getY(); // 通知重绘 postInvalidate(); break; } /* * 备注1:此处一定要将return super.onTouchEvent(event)修改为return true,原因是: * 1)父类的onTouchEvent(event)方法可能没有做任何处理,但是返回了false。 * 2)一旦返回false,在该方法中再也不会收到MotionEvent.ACTION_MOVE及MotionEvent.ACTION_UP事件。 */ //return super.onTouchEvent(event); return true; } }
懂得运用View的绘画三要素,画出自己想要的图也不难。
ImageView 绘制图片就不多说了,看一下例子吧 public class RoundImageView extends ImageView { private Bitmap mBitmap; private Rect mRect = new Rect(); private PaintFlagsDrawFilter pdf = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG); private Paint mPaint = new Paint(); private Path mPath=new Path(); public RoundImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } //传入一个Bitmap对象 public void setBitmap(Bitmap bitmap) { this.mBitmap = bitmap; } private void init() { mPaint.setStyle(Paint.Style.STROKE); mPaint.setFlags(Paint.ANTI_ALIAS_FLAG); mPaint.setAntiAlias(true);// 抗锯尺 } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(mBitmap == null) { return; } mRect.set(0,0,getWidth(),getHeight()); canvas.save(); canvas.setDrawFilter(pdf); mPath.addCircle(getWidth() / 2, getWidth() / 2, getHeight() / 2, Path.Direction.CCW); canvas.clipPath(mPath, Region.Op.REPLACE); canvas.drawBitmap(mBitmap, null, mRect, mPaint); canvas.restore(); } }
综上所述,为什么视频技术入门要先了解图片绘制,那么图片绘制的API也有多种,为什么选择用SurfaceView这个API,因为其一,绘制是在子线程中进行绘制的,其二,可能绘制出高效复杂的UI效果,其三,使用双缓冲机制,播放视频时画面更流畅。
原创作者:安仔夏天勤奋,原文链接: https://www.jianshu.com/p/70912c55a03b
欢迎关注我的微信公众号「码农突围」,分享Python、Java、大数据、机器学习、人工智能等技术,关注码农技术提升•职场突围•思维跃迁,20万+码农成长充电第一站,陪有梦想的你一起成长。
多媒体
2020-04-02 20:17:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
SVT-AV1是开源的AV1编解码器实现,托管在GitHub上[1]。如我们先前的文章所述[2],英特尔和Netflix自2018年8月以来一直在就SVT-AV1编解码器框架进行合作。团队一直密切合作进行SVT-AV1的开发、交流架构决策;实施新工具并改善压缩效率。自从项目开源后更多技术合作伙伴和开源社区为SVT-AV1做出非常多的贡献。此篇技术博客中,我们将继续报告SVT-AV1项目的当前状态以及编解码器的特性与性能。
文/ Andrey Norkin, Joel Sole, Mariana Afonso,Kyle Swanson, Agata Opalach, Anush Moorthy, Anne Aaron
译 / 蒋默邱泽
原文
https://netflixtechblog.com/svt-av1-an-open-source-av1-encoder-and-decoder-ad295d9b5ca2
SVT-AV1代码库状态
SVT-AV1代码库包括一个AV1编码和解码器,它们共享大量的代码。SVT-AV1解码器功能齐全,并符合所有三个配置文件(Main,High& Professional)的AV1规范。
SVT-AV1编码器支持所有对压缩效率有助力的AV1工具。与最新的libaom主版本(AV1参考软件)相比,SVT-AV1在压缩效率方面相近,同时在多核平台上使用其特有的并行化处理功能时编码延迟显著降低。
SVT-AV1中的代码超过90%是用C语言写的,可跨平台进行编译。除了允许进行更灵活实验的纯C函数实现之外,编解码器大量采用了汇编以及针对x86平台的intrinsic优化。了解SVT-AV1的主要功能特性,请关注下一部分。这些功能使得SVT-AV1可以在高压缩效率竞争力的条件下具有更高的性能。SVT-AV1还包括大量有关编码器设计的文档[3],旨在促进新开发人员快速上手。
结构特点
英特尔SVT-AV1开发的目标之一是创建一种具有高性能和可扩展性的AV1编解码器。
SVT-AV1在编码过程的多个阶段实现并行化,这使得它能够适应可用内核的数量,包括具有大量内核线程数量的最新服务器。这使得SVT-AV1可以在有效缩短编码时间的同时仍保持现有压缩率。
SVT-AV1编码器使用多维度(基于线程,帧/块和基于片段)并行、多阶段划分决策、基于块的多阶段和多类别决策以及RD优化分类,以在压缩和性能之间实现有吸引力的折衷。SVT体系结构的另一个特征是开环分层运动估计,这使得运动估计的第一阶段与编码其余部分解耦过程成为可能。
压缩率和性能
编码性能
SVT-AV1在慢速设置下达到与libaom相似的压缩效率。在编解码开发过程中,我们一直在跟踪https://videocodectracker.dev/站点的压缩和编码结果。下图显示了随着时间的推移,SVT-AV1与libaom编码器相比在压缩效率方面的改进。请注意,随着时间的推移,libaom压缩也在不断迭代,下面的图表显示SVT-AV1赶上了移动的目标。在该图中,Y轴显示了根据三个度量实现与libaom编码器类似的质量所需的额外码率(以%表示)。该图显示了两种编解码器中2-pass编码模式的结果。SVT-AV1使用4线程模式,而libaom运行在单线程模式。研究中常用的1-pass固定QP编码模式的SVT-AV1结果更具竞争力,如下所述。
在2-pass编码模式下随时间降低的SVT-AV1和libaom之间的BD-rate(8-bit位深)
下表列出了在Objective-1-FAST[4]测试集上SVT-AV1与libaom的比较结果。为了估计编码时间,我们使用英特尔®至强®铂金 8170@2.10 GHz芯片(具有26核52线程核心和96 GB 内存)处理并行编码(这里没有采用Intel&AMD最新同级芯片处理数据可能会有另一番惊喜)。两个编解码器都使用16个画面的双向分层预测结构。给出了具有固定帧级QP偏移量的单程模式的结果。使用单线程压缩模式。如下我们计算各种质量度量的BD-rate:YUV分量的PSNR、VMAF和MS-SSIM。负的BD-rate表示SVT-AV1编码相同的质量时所需的比特率相对较低。如下所示,与libaom相比,SVT-AV1的编码时间减少了16.5%,同时压缩能力略有提高。请注意!编码时间比率可能因平台支持的指令集而异。针对libaom主分支(Git Hash Fe72512),在SVT-AV1CS2分支(当前正在并入主分支git hash 3a19f29的开发分支)上获得了结果。用于计算BD-Rate的QP值为:20、32、43、55、63。

在固定QP偏移的1-pass编码模式下,SVT-AV1与libaom的BD速率。负数表示达到相同质量级别所需的码率降低。与libaom相比,SVT-AV1的总体编码时间差是所有序列和QPS的总CPU时间的变化
*整体编码CPU时间差以测试的所有序列和QPS的总CPU时间与锚的CPU总时间相比的变化来计算。它不等于每个序列值的平均值。对于每个序列,编码CPU时间差被计算为该序列的所有QP的总CPU时间的变化。
由于Objective-1-FAST测试集中的所有序列都有60帧,因此两个编解码器都使用一个关键帧。已使用以下命令行参数比较编解码器。
libaom参数: --passes=1 --lag-in-frames=25 --auto-alt-ref=1 --min-gf-interval=16 - -max-gf-interval=16 --gf-min-pyr-height=4 --gf-max-pyr-height=4 --kf- min-dist=65 --kf-max-dist=65 --end-usage=q --use-fixed-qp-offsets=1 - -deltaq-mode=0 --enable-tpl-model=0 --cpu-used=0
SVT-AV1参数: --preset1--scm2--keyint63--lookahead0--lp1
以上结果证明了SVT-AV1的优良客观性能。此外SVT-AV1还包括一些主观质量工具的实现,如果编解码器配置为主观质量则可以使用这些工具。
解码性能
在Objective-1-FAST测试集上,SVT-AV1解码器在单线程模式下比libaom略快,在4线程模式下有较大的改进。当使用4线程模式解码具有多块的码流时,我们观察到比libaom解码器有更大的速度提升。该测试已在Windows、Linux和MacOS平台上执行。我们相信对于研究解码器来说性能是令人满意的,其中折衷方案更倾向于更容易的实验,而不是生产解码器所需的进一步优化。
测试框架
为了帮助确保编解码器的一致性,特别是对于新的代码贡献,所有代码已经被单元测试和端到端测试全面覆盖。单元测试构建在Google测试框架之上。对于GitHub操作支持的对代码库的每个拉取请求,都会自动触发单元测试和端到端测试。这些测试支持分片,并且它们并行运行以加快拉取请求的周转时间。
此拉入请求的单元和e2e测试通过
NEXT 未来
在过去的几个月里,SVT-AV1已经成为一个完整成熟的编/解码器软件,提供具有竞争力的压缩效率和性能折衷。该项目得到了广泛的单元测试覆盖和文档的支持。
我们希望SVT-AV1代码库有助于进一步利用AV1,并鼓励在当前AV1工具的基础上进行更多的研究和开发。我们相信SVT-AV1显示出的优势使其成为一个很好的实验和研究平台。我们邀请工业界和学术界的同事查看Github上的项目,联系代码库维护人员询问问题和意见,或者参加SVT-AV1Open Dev会议[5]。我们欢迎更多的开发贡献者参与这个项目。

参考:
[1]https://github.com/OpenVisualCloud/SVT-AV1/
[2]https://mp.weixin.qq.com/s/7ZmYrWJH6JrgOSnd0j0w8A
[3]https://github.com/OpenVisualCloud/SVT-AV1/tree/master/Docs
[4]https://tools.ietf.org/html/draft-ietf-netvc-testing-09#section-5.2.5
[5]https://github.com/OpenVisualCloud/SVT-AV1/issues/1134
多媒体
2020-04-02 11:25:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
一、前言
图片地图这个模块是后面新增加进去的,主要是安防领域还有很多应用场景是一个区域比如就一个学校,提供一个学校的平面图或者鸟瞰图,然后在该地图上放置对应的摄像机,双击该摄像机图标可以查看对应的实时视频,报警的时候弹出报警视频,切换到当前报警对应的地图,闪烁设备图标,用户可以在右侧的地图列表中单击切换对应的地图查看对应的摄像机位置和分布图,如果再配上鸟瞰图就更加美观,一般大领导就喜欢这种感官上的刺激欣赏,说不准一开心就把项目批准了,经费下来了。
关于图片地图这个功能,在很多系统中都用到了,比如上次的气体安全管理系统,除了提供设备分布图以外,还需要提供移动设备的模式来调整设备的位置,这个为此特意封装了控件来完成这个功能,该控件完全开源。
设备防区开源地址: https://gitee.com/feiyangqingyun/QWidgetDemo https://github.com/feiyangqingyun/QWidgetDemo 文件名称:buttondefence
体验地址: https://gitee.com/feiyangqingyun/QWidgetExe https://github.com/feiyangqingyun/QWidgetExe 文件名称:bin_video_system.zip
二、功能特点 支持16画面切换,全屏切换等,包括1+4+6+8+9+13+16画面切换。 支持alt+enter全屏,esc退出全屏。 自定义信息框+错误框+询问框+右下角提示框。 17套皮肤样式随意更换,所有样式全部统一,包括菜单等。 云台仪表盘鼠标移上去高亮,八个方位精准识别。 底部画面工具栏(画面分割切换+截图声音等设置)移上去高亮。 可在配置文件更改左上角logo+中文软件名称+英文软件名称。 封装了百度地图,三维切换,设备点位,鼠标按下获取经纬度等。 堆栈窗体,每个窗体都是个单独的qwidget,方便编写自己的代码。 顶部鼠标右键菜单,可动态控制时间CPU+左上角面板+左下角面板+右上角面板+右下角面板的显示和隐藏,支持恢复默认布局。 工具栏可以放置多个小图标和关闭图标。 左侧右侧可拖动拉伸,并自动记忆宽高位置,重启后恢复。 双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。 摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。 视频画面窗体支持拖曳交换,瞬间响应。 双击节点+拖曳节点+拖曳窗体交换位置,均自动更新url.txt。 支持从url.txt中加载16通道视频播放,自动记忆最后通道对应的视频,软件启动后自动打开播放。 右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。 集成百度地图,可以添加设备对应位置,自动生成地图,支持缩放和三维地图,提供地图风格选择,共12种风格。 视频拖动到通道窗体外自动删除视频。 鼠标右键可删除当前+所有视频,截图当前+所有视频。 录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。 在pro文件中可以自由开启是否加载地图。 视频播放可选四种内核自由切换,vlc+ffmpeg+easyplayer+海康sdk,均可在pro中设置。 可设置1+4+9+16画面轮询,可设置轮询间隔以及轮询码流类型等,直接在主界面底部工具栏右侧单击启动轮询按钮即可,再次单击停止轮询。 默认超过10秒钟未操作自动隐藏鼠标指针。 支持onvif搜素设备,支持任意onvif摄像机,包括但不限于海康大华宇视天地伟业华为等,支持onvif云台控制。 高度可定制化,用户可以很方便的在此基础上衍生自己的功能,支持linux系统。
三、效果图
四、核心代码 #include "frmmapimage.h" #include "ui_frmmapimage.h" #include "quiwidget.h" #include "devicehelper.h" #include "buttondefence.h" #include "frmvideopreview.h" frmMapImage::frmMapImage(QWidget *parent) : QWidget(parent), ui(new Ui::frmMapImage) { ui->setupUi(this); this->initForm(); } frmMapImage::~frmMapImage() { delete ui; } void frmMapImage::hideEvent(QHideEvent *) { DeviceHelper::saveDeviceButtonPosition(); } void frmMapImage::initForm() { connect(AppEvent::Instance(), SIGNAL(doubleClicked(ButtonDefence *)), this, SLOT(doubleClicked(ButtonDefence *))); ui->listWidget->setFixedWidth(App::RightWidth); DeviceHelper::setLabel(ui->label); DeviceHelper::setListWidget(ui->listWidget); DeviceHelper::initDeviceMap(); DeviceHelper::initDeviceButton(); ui->listWidget->setCurrentRow(0); on_listWidget_pressed(); } void frmMapImage::doubleClicked(ButtonDefence *btn) { //取出视频流地址打开 QString url = btn->property("rtspMain").toString(); if (!url.isEmpty()) { frmVideoPreview *video = new frmVideoPreview(); video->setUrl(url); video->show(); } } void frmMapImage::on_listWidget_pressed() { int row = ui->listWidget->currentRow(); if (row < 0) { return; } DeviceHelper::initDeviceMapCurrent(DBData::MapNames.at(row)); }
多媒体
2020-01-03 09:54:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
一、前言
摄像机管理在整个系统中是数据库部分最核心的,只有添加了摄像机信息,才能进行加载,生成树状列表等,摄像机表信息的字段内容改过好几次,有可能后期还需要修改,目前摄像机表信息主要包括摄像机编号、摄像机名称、所属录像机、厂家、设备地址、媒体地址、云台地址、主码流地址、子码流地址、经纬度、背景地图、X坐标、Y坐标、用户姓名、用户密码、启用状态、安装位置。其中设备地址、媒体地址、云台地址、主码流地址、子码流地址这五个是在通过onvif搜索设备的时候拿到,码流地址是必须的,其他三个可以为空,这三个用来云台控制。背景地图表示该摄像机对应的图片地图模块的图片文件名称,默认在可执行文同一目录下的map文件夹,XY坐标为对应地图上的位置,经纬度为在线地图和离线地图中的位置,用户名和密码为对应onvif登录到该摄像机的用户信息,用户名和密码信息必须正确,否则在云台控制的时候会失败,每次云台控制下发的数据都带了用户信息,用户信息不正确的话会执行失败,这个用户和摄像机的web界面的登录用户不一样,一般都是在摄像机的后台onvif用户信息的地方进行设置。
分页组件开源地址: https://gitee.com/feiyangqingyun/QWidgetDemo https://github.com/feiyangqingyun/QWidgetDemo 文件名称:dbpage
体验地址: https://gitee.com/feiyangqingyun/QWidgetExe https://github.com/feiyangqingyun/QWidgetExe 文件名称:bin_video_system.zip
二、功能特点 支持16画面切换,全屏切换等,包括1+4+6+8+9+13+16画面切换。 支持alt+enter全屏,esc退出全屏。 自定义信息框+错误框+询问框+右下角提示框。 17套皮肤样式随意更换,所有样式全部统一,包括菜单等。 云台仪表盘鼠标移上去高亮,八个方位精准识别。 底部画面工具栏(画面分割切换+截图声音等设置)移上去高亮。 可在配置文件更改左上角logo+中文软件名称+英文软件名称。 封装了百度地图,三维切换,设备点位,鼠标按下获取经纬度等。 堆栈窗体,每个窗体都是个单独的qwidget,方便编写自己的代码。 顶部鼠标右键菜单,可动态控制时间CPU+左上角面板+左下角面板+右上角面板+右下角面板的显示和隐藏,支持恢复默认布局。 工具栏可以放置多个小图标和关闭图标。 左侧右侧可拖动拉伸,并自动记忆宽高位置,重启后恢复。 双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。 摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。 视频画面窗体支持拖曳交换,瞬间响应。 双击节点+拖曳节点+拖曳窗体交换位置,均自动更新url.txt。 支持从url.txt中加载16通道视频播放,自动记忆最后通道对应的视频,软件启动后自动打开播放。 右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。 集成百度地图,可以添加设备对应位置,自动生成地图,支持缩放和三维地图,提供地图风格选择,共12种风格。 视频拖动到通道窗体外自动删除视频。 鼠标右键可删除当前+所有视频,截图当前+所有视频。 录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。 在pro文件中可以自由开启是否加载地图。 视频播放可选四种内核自由切换,vlc+ffmpeg+easyplayer+海康sdk,均可在pro中设置。 可设置1+4+9+16画面轮询,可设置轮询间隔以及轮询码流类型等,直接在主界面底部工具栏右侧单击启动轮询按钮即可,再次单击停止轮询。 默认超过10秒钟未操作自动隐藏鼠标指针。 支持onvif搜素设备,支持任意onvif摄像机,包括但不限于海康大华宇视天地伟业华为等,支持onvif云台控制。 高度可定制化,用户可以很方便的在此基础上衍生自己的功能,支持linux系统。
三、效果图
四、核心代码 void frmConfigIpc::on_btnAdd_clicked() { int count = model->rowCount(); model->insertRow(count); int ipcID = model->index(count - 1, 0).data().toInt() + 1; QString ipcName = model->index(count - 1, 1).data().toString(); QString nvrName = model->index(count - 1, 2).data().toString(); QString ipcType = model->index(count - 1, 3).data().toString(); QString onvifAddr = model->index(count - 1, 4).data().toString(); QString mediaAddr = model->index(count - 1, 5).data().toString(); QString ptzAddr = model->index(count - 1, 6).data().toString(); QString rtspMain = model->index(count - 1, 7).data().toString(); QString rtspSub = model->index(count - 1, 8).data().toString(); QString ipcPosition = model->index(count - 1, 9).data().toString(); QString ipcImage = model->index(count - 1, 10).data().toString(); int ipcX = model->index(count - 1, 11).data().toInt(); int ipcY = model->index(count - 1, 12).data().toInt(); QString userName = model->index(count - 1, 13).data().toString(); QString userPwd = model->index(count - 1, 14).data().toString(); QString ipcEnable = model->index(count - 1, 15).data().toString(); QString ipcAddr = model->index(count - 1, 16).data().toString(); if (ipcName.startsWith("摄像机#")) { ipcName = QString("摄像机#%1").arg(ipcID); } ipcX += App::DeviceWidth; if (ipcX > App::MapWidth - 100) { ipcX = 5; ipcY += App::DeviceHeight; } if (count == 0) { ipcID = 1; ipcName = "摄像机#1"; nvrName = "录像机#1"; ipcType = "other"; //onvifAddr = "http://192.168.1.128/onvif/device_service"; //mediaAddr = "http://192.168.1.128//onvif/media_service"; //ptzAddr = "http://192.168.1.128//onvif/ptz_service"; rtspMain = "rtsp://192.168.1.128:554/0"; rtspSub = "rtsp://192.168.1.128:554/1"; ipcPosition = "121.534942,31.307706"; ipcImage = "无"; ipcX = 5; ipcY = 5; userName = "admin"; userPwd = "admin"; ipcEnable = "启用"; ipcAddr = "录像机的安装位置"; } //设置新增加的行默认值 model->setData(model->index(count, 0), ipcID); model->setData(model->index(count, 1), ipcName); model->setData(model->index(count, 2), nvrName); model->setData(model->index(count, 3), ipcType); model->setData(model->index(count, 4), onvifAddr); model->setData(model->index(count, 5), mediaAddr); model->setData(model->index(count, 6), ptzAddr); model->setData(model->index(count, 7), rtspMain); model->setData(model->index(count, 8), rtspSub); model->setData(model->index(count, 9), ipcPosition); model->setData(model->index(count, 10), ipcImage); model->setData(model->index(count, 11), ipcX); model->setData(model->index(count, 12), ipcY); model->setData(model->index(count, 13), userName); model->setData(model->index(count, 14), userPwd); model->setData(model->index(count, 15), ipcEnable); model->setData(model->index(count, 16), ipcAddr); ui->tableView->setCurrentIndex(model->index(count, 0)); } void frmConfigIpc::on_btnSave_clicked() { model->database().transaction(); if (model->submitAll()) { model->database().commit(); DBHelper::loadIpcInfo(); DeviceHelper::initDeviceTree(); DeviceHelper::initVideoIcon(); DeviceHelper::initDeviceMap(); DeviceHelper::initDeviceButton(); AppEvent::Instance()->slot_saveIpcInfo(); } else { model->database().rollback(); QUIHelper::showMessageBoxError("保存信息失败,信息不能为空,请重新填写!"); } } void frmConfigIpc::on_btnDelete_clicked() { if (ui->tableView->currentIndex().row() < 0) { QUIHelper::showMessageBoxError("请选择要删除的摄像机!"); return; } if (QUIHelper::showMessageBoxQuestion("确定要删除该摄像机吗? 删除后不能恢复!") == QMessageBox::Yes) { int row = ui->tableView->currentIndex().row(); model->removeRow(row); model->submitAll(); ui->tableView->setCurrentIndex(model->index(model->rowCount() - 1, 0)); DBHelper::loadIpcInfo(); DeviceHelper::initDeviceTree(); DeviceHelper::initVideoIcon(); AppEvent::Instance()->slot_saveIpcInfo(); } } void frmConfigIpc::on_btnReturn_clicked() { model->revertAll(); } void frmConfigIpc::on_btnClear_clicked() { if (model->rowCount() <= 0) { return; } if (QUIHelper::showMessageBoxQuestion("确定要清空所有摄像机信息吗?") == QMessageBox::Yes) { DBHelper::clearIpcInfo(); model->select(); DBHelper::loadIpcInfo(); DeviceHelper::initDeviceTree(); DeviceHelper::initVideoIcon(); AppEvent::Instance()->slot_saveIpcInfo(); } }
多媒体
2019-12-29 14:53:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
学 GIS 空间数据库的时候,拓扑方面内容笔记
拓扑的定义
拓扑是研究几何图形或空间在连续改变形状后还能保持不变的一些性质的一个学科。 它只考虑物体间的位置关系而不考虑它们的形状和大小 。
“拓扑”就是把实体抽象成与其大小、形状无关的“点”,而把连接实体的线路抽象成“线”,进而以图的形式来表示这些点与线之间关系的方法,其目的在于研究这些点、线之间的相连关系。表示点和线之间关系的图被称为拓扑结构图。拓扑结构与几何结构属于两个不同的数学概念。在几何结构中, 我们要考察的是点、线、面之间的位置关系,或者说几何结构强调的是点与线所构成的形状及大小。如梯形、正方形、平行四边形及圆都属于不同的几何结构,但从拓扑结构的角度去看,由于点、线间的连接关系相同,从而具有相同的拓扑结构即环型结构。也就是说,不同的几何结构可能具有相同的拓扑结构。
如三角形变成四边形、原型、环形,角度、长度、面积、形状等等都很可能发生变化。此时,不必考虑它们的形状和大小(如长度、面积、形状等等这些),只考虑物体间的位置、结构关系,只专注于在连续改变形状后还能保持不变的一些性质(如他们都是一个圈),这就是拓扑学。
拓扑学历史
拓扑英文名是Topology,直译是地志学,最早指研究地形、地貌相类似的有关学科。
几何拓扑学是十九世纪形成的一门数学分支,它属于几何学的范畴。有关拓扑学的一些内容早在十八世纪就出现了。那时候发现的一些孤立的问题,在后来的拓扑学的形成中占着重要的地位。 1679年德国数学家莱布尼茨提出的名词 拓扑学,起初叫形势分析学,他在17世纪提出“位置的几何学”(geometria situs)和“位相分析”(analysis situs)的说法。 1736年欧拉在解决了七桥问题,给当时数学界引起很多思考; 1750年欧拉在发表了多面体公式; 1833年高斯在电动力学中用线积分定义了空间中两条封闭曲线的环绕数。 1847年 J.B.利斯廷根据希腊文τπο和λγο(“位置”和“研究”),提出Topology这一数学名词,即拓扑学。Topology,直译是地志学,最早指研究地形、地貌相类似的有关学科。 1851年左右,即19世纪中期,德国数学家黎曼在复变函数的研究中提出了黎曼面的几何概念,并且强调为了研究函数、研究积分,就必须研究形势分析学,从此数学界开始了现代拓扑学的系统研究。


不同学科对拓扑的定义不尽相同
集合拓扑: 拓扑是集合上定义的一种结构 。
点集拓扑学
点集拓扑学(Point Set Topology),有时也被称为一般拓扑学(General Topology) ,是数学的拓扑学的一个分支。
它研究拓扑空间以及定义在其上的数学结构的基本性质。这一分支起源于以下几个领域:对实数轴上点集的细致研究,流形的概念,度量空间的概念,以及早期的泛函分析。
点集拓扑学定义
拓扑是一个包含一个集合X连同和X的子集族Σ(称为开集系)的二元组(X,Σ),它满足如下三个公理: 开集的并集是开集。 有限个开集的交集是开集。 X和空集∅是开集。
设T为非空集X的子集族。若T满足以下条件: X与空集都属于T; T中任意两个成员的交属于T; T中任意多个成员的并属于T; 则T称为X上的一个拓扑。具有拓扑T的集合X称为拓扑空间,记为(X,T)。
也等价于: X和空集都属于T; T中任意多个成员的并集仍在T中; T中有限多个成员的交集仍在T中。
此时称称T中的成员为这个拓扑空间的开集。最普通的例子便是实数集上的距离拓扑,这与我们通常对实数的认识相同。最简单(粗)的拓扑为平凡拓扑,它只包含T本身和空集,最复杂(细)的拓扑的构成开集为T的所有子集。
同一个集合X,若指定不同的拓扑,则构造出不同的拓扑空间。凡属于X的子集称为X的一个关于T的开子集,即开集。开子集关于全集的补集,称为闭子集,即闭集。一个集合是不是开/闭子集,取决于拓扑的指定。由定义,X本身和空集是既开又闭的子集。
本质上,拓扑就是要给一个集合指定一个几何结构,然后这个集合就成了一个我们可以研究的空间。比如,有了拓扑和开集的定义后,我们就可以摆脱大一数学分析的ε-δ来给出更一般的连续性定义:设A和B是两个拓扑空间,A到B的映射f称为连续的,若任何B的开集在f下的原象是A的开集。这样我们对于函数的研究将不再局限于实数,而是搬到更一般的拓扑空间内了。



平面拓扑关系
对于一般的拓扑关系,一图概括如下
Egenhofer和Franzosa在1991年共同撰写的论文Point-Set Topological Spatial Relations,为空间拓扑(九交模型)奠定了重要基础。
依据集合论,作者对于点集拓扑空间定义了以下基本概念,以描述空间对象: Interior(内部) :对于 , interior指的是所有包含 的开放集合的并集。对于空间对象,可以认为是空间对象的内部。 Closure(闭包) :对于 , closure指的是所有包含 的闭集合的交集。对于空间对象,可以认为是空间对象整体。 Boundary(边界) :对于 , boundary指的是Y的闭包与Y的补集的闭包的交集,即 。对于空间对象,可以认为是空间对象的边界。
简而言之,一个空间对象可定义为由内部+边界构成。
根据以上三条定义可知以下两命题: 。即:内部和边界的交集为空。 。即:内部和边界的并集为整个对象。
九交模型
在一个平面R2上,两个对象A和B之间的二元拓扑关系要基于以下的相交情况:A的内部(A°)、边界(αA)和外部(A-)与B的内部(B°)、边界(αB)和外部(B-)之间的交。

考虑取值有空(0)和非空(1),可以确定有256种二元拓扑关系。对于嵌在R2中的二维区域,有八个关系是可实现的,并且它们彼此互斥且完全覆盖。这些关系为:相离(disjoint)、相接(meet)、交叠(overlap)、相等(equal)、包含(contain)、在内部(inside)、覆盖(cover)和被覆盖(covered by)。
九交模型
三维空间拓扑关系 点-点空间关系2种:相离、相等; 点-线空间关系3种:相离、相接、包含于; 点-面空间关系3种:相离、相接、包含于; 点-体空间关系3种:相离、相接、包含于; 线-线空间关系7种:相离、相交、交叠、相等、相接、包含于、包含; 线-面空间关系5种:相离、相接、进入、穿越、包含于; 线-体空间关系5种:相离、相接、进入、穿越、包含于; 面-面空间关系10种:相离、相接、交叠、相等、包含于、包含、覆盖、被覆盖、穿越、被穿越; 面-体空间关系8种:相离、相接、交叠、进入、包含于、包含、穿越、被穿越; 体-体空间关系8种:相离、相接、进入、相等、包含于、包含、穿越、被穿越。
基本空间拓扑关系的计算
点与直线的关系计算
直线方程:
Ax+By+C=0
A=y1-y2,
B=x1-x2,
C=y2x1-y1x2
令S=Axi+Byi+C 当S<0 点在顺时针方向上; 当S=0 点在直线上; 当S<0 点在逆指针方向上。
两条直线关系的计算
直线方程:
Ax+By+C=0
Ex+Fy+G=0
当FA-EB=0时,两条直线的交点不存在;否则,交点坐标为:
xi=(GB-FC)/(FA-EB)
yi=(CE-AG)/(FA-EB)

空间目标之间的拓扑关系推理
两条线的直线段之间基本空间拓扑关系的推理
点与其他类型空间目标之间的拓扑关系决策树
线与面之间的全域空间拓扑关系决策树
面与面之间的全域空间拓扑关系基本类型的决策树

空间度量关系
度量关系是在欧氏空间(Euclidean Space)(Blumenthal,1970)和度量空间(Metric Space)(Dhage,1992)上进行的操作,它是一切空间数据定量化的基础。它包含长度、周长、面积、距离等定量的度量关系,其中最主要的度量空间关系是空间对象之间的距离关系。
欧几里德距离定义如下(Kolountzakis and Kutulakos,1992):
曼哈顿距离是两点在南北方向上的距离加在东西方向上的距离(Wu et al.,1987),即:
空间顺序关系及描述方法
锥形模型
每区域赋予东、南、西和北,为得到更精确的方向关系可对其再进行细分得8或16方向。
最小外接矩形模型

该模型通过延伸目标的MBR的边,将空间划分为9个区域,分别表示为北、东北、东、东南、南、西南、西、西北和目标MBR所在的中心方向。
Freksa-Zimmermann模型
以直线段为参考的定性空间方向模型:以直线为空间参考目标,把二维空间分解为15个方向区域。
以点为参考目标的基本空间方向
点A与点B的空间方向关系可以用向量AB与正北方向的夹角(顺时针)来描述。
以直线为参考目标的基本空间方向
点与线或面之间的空间方向关系
线与点、线或面之间的空间方向计算与描述
面与点、线、面之间的空间方向关系计算与描述
点与点之间距离&点与线之间距离:dPL(P,L)=min{d1,d2,…dn} 线与线之间的距离:d(L1,L2)=min{d(P1,P2)|P1∈L1,P2 ∈L2} 点与面之间的距离: “中心距离”是点P与面A中几何中心或者重心之间的距离, “最小距离”是指点P与面A中所有点之间距离的最小值, “最大距离”是指点P与面A中所有点之间距离的最大值。 面与面之间的距离 “中心距离”是指两个面状物体的质心之间的距离; “最小距离”是指面A1中的点P1与A2中的点P2之间的距离的最小值; “最大距离”是指面A1中的点P1与A2中的点P2之间的距离的最大值。 (a) 点A与点B之间的空间方向关系。 (b)点A与直线BC之间的空间方向关系,以角平分线L的方位表示。 (c) 用两条直线的中点代表代表其方位。 (a) 直线AB和直线CD的方向可用向量EF(E和F分别为两直线的中点)来描述。 (b)直线AB和点C的方向关系。 (c) 划分直线段AB的方向片,点C相对直线AB的关系可描述为点C在直线AB的哪个方向片中。 (d)直线AB和直线CD的方向可用向量EF(E和F分别为两直线的中点)来描述,或用向量ED和向量EC来定义。 (a) 方向线PS和PE定义了点A与线L之间的全域空间方向关系,点A与P1、P2、P3(中点)的连线定义了点A与不同直线段的局域空间方向关系。 (b)方向线PS和PE重和,说明点A被线L包围,这是全域空间方向关系,点A与P1、P2、P3、P4(中点)的连线定义了点A与不同直线段的局域空间方向关系。 (c)方向线PS和PE定义了点A与面B之间的全域空间方向关系,用方向线P1、P2把面域B分为3部分,每部分可以用该锥形的角平分线描述方向关系,这3部分的面积与面积B的总面积之比分别为B1、B2、B3。也可以用该锥形的每个角平分线在面内的长度与角平分线在面内的总长度之比L1、L2、L3来表示。 (d)方向线PS和PE重和,说明点A被面B包围,这是全域空间方向关系,面域不同和点A之间的局域空间方向关系描述方法与(c)同。 (a) 线ABCD与点E之间的全域空间方向关系为“相同”,直线段AB与点E之间的局域空间方向关系为“西”。 (b) 反映线与线之间的全域空间方向关系,直线段AB与线L2的每条直线段和线的任意子集之间都有局域空间方向关系。 (c) 线与面的全域空间方向关系和局域空间方向关系均可象(b)一样计算和描述。 (a) 面P与点C之间的全域空间方向关系为“相同”,面P的直线AB与点C之间的局域空间方向关系为“北”。 (b) 面P与直线EFG之间的全域空间方向关系和局域空间方向关系如图所示,前者为“东”、“相同”和“南”,而后者为“东”。 (c) 把区域栅格化,判断子区域与源目标的全域空间方向关系和局域空间方向关系。

转载 本站 文章《 代数拓扑\集合拓扑\代数拓扑\拓扑关系\拓扑结构_笔记 》, 请注明出处: https://www.zhoulujun.cn/html/theory/math/2019_0929_8164.html
多媒体
2019-12-10 18:22:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 1: 合并需要简化的所有道路的图层 arcpy.Merge_management(["乡镇村道2_polyline","县道_polyline","国道_polyline","城市快速路_polyline","省道_polyline","高速_polyline"],"E:/temp/jinan/road") 2:添加 LEVEL 字段(编辑状态下不能添加字段) 值都设置为1 为了 之后合并道路使用 包含道路分类信息的字段。将只合并平行且接近的相同类型道路。 值 0(零)将锁定要素以阻止其参与合并。 合并分开的道路 arcpy.MergeDividedRoads_cartography("road", "LEVEL", "200 meters", "E:/temp/road_polyline1")
报错: in MergeDividedRoads raise e ExecuteError: 某些几何体为多部件
应用数据管理工具-要素-多部件至单部件工具
选取road进行多部件至单部件操作
road_MultipartToSinglepar 合并分开的道路 arcpy.MergeDividedRoads_cartography("road_MultipartToSinglepar", "LEVEL", "200 meters", "E:/temp/road_polyline1")
200 meters 是 merge_distance
要合并的相互平行的同类道路要素的最小距离间隔(使用指定的单位)。此距离必须大于零。
如果单位是磅、毫米、厘米或英寸,则值被视为使用页面单位,还会将参考比例考虑在内。
多媒体
2019-12-02 11:23:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
背景
最近制作思维导图想添加自己的水印,网上很多例子都是使用ImageMagick来完成。但是不少代码在本地并不可行。经过一番试验,找到两个方法。
方法一
代码
stackoverflow方法 改良: convert 'ISO_IEC 25010.jpg' \ \( \ -size 60x60 xc:none \ -fill grey \ -gravity center \ -draw "text 0,0 'wffger'" -rotate -30 -write mpr:wm \ +delete \ +clone -fill mpr:wm -draw 'color 0,0 reset' \ \) \ -compose Multiply \ -composite \ 'ISO_IEC 25010-mark1.jpg'
说明 -size,控制大小,间接设置水印间距。 xc:none,设置水印没有背景色,xc为"X Constant Image"。 -fill,设置水印字体颜色,不能设置成白色,否则被-compose Multiply设置成透明
方法二
代码
ImageMagick 官方水印指南: convert -size 600x600 xc:none -fill grey \ -gravity NorthWest -draw "text 10,10 'wffger'" \ -gravity SouthEast -draw "text 5,15 'wffger'" \ miff:- |\ composite -tile - 'ISO_IEC 25010.jpg' 'ISO_IEC 25010-mark2.jpg'
说明 -size,设置水印图像大小。 -tile,把水印平铺。
环境 ydx@ydx-mf:~/文档 $ uname -a Linux ydx-mf 5.7.11-200.fc32.x86_64 #1 SMP Wed Jul 29 17:15:52 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux ydx@ydx-mf:~/文档 $ rpm -qi ImageMagick Name : ImageMagick Epoch : 1 Version : 6.9.11.22 Release : 1.fc32 Architecture: x86_64
多媒体
2020-08-13 01:38:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
画画最怕什么?瓶颈期
最难受的是什么?遇到瓶颈期
每个人在画画的过程中都会遇到瓶颈期,有的人可能因此放弃画画自暴自弃,有的人坚持过去了,就画功猛进,那么遇到瓶颈期该怎么办?
在你一直平常的画着画时,突然有一天,你找不到画画的激情和灵感了,你怎么画也画不好时,“越丑越画,越画越丑”这样的自我否定怀疑,这就是画画的瓶颈期了,顺便在此推荐大家可以搜一下:艺学绘,或者下载艺学绘APP,艺学绘的网站上面有很多的绘画课程,还有一个魔鬼特训班,魔鬼特训班大家可以挑战一下,很多人的学习效果都非常不错!
每个人对待绘画瓶颈期的方式会不同,可能很多人并没有意识到绘画瓶颈期,像小编学画画的时候,在绘画瓶颈期的时候,起初也会些许难过、急躁、想放弃,后来慢慢的临摹、看画展观摩别人的画慢慢静下心来画画,坚持下来也就过去了。
画画进步是呈梯度性的提升,刚开始学画画时,你会发现自己几乎是每天都在一点点的进步,进步的画功自己都可以观察出来,随着画画时间的长度,进步的速度就越慢,这就是绘画中的“瓶颈期”。
这个瓶颈期只要坚持的画下去就会过渡的,保持平常心非常的重要,这一关跨越过去了,整个就像打通了任督二脉一样。
那么遇到瓶颈期到底要怎么办呢?
改变现有的学习方式
正确的认识自己
放松心情别给自己压力
换个角度看自己,冷静下来,重新审视自己的优点和缺点,把自己的毛病一一拣出来,借着向别人学习,有针对性地解决自己的毛病,你肯定能有进步。再回头一看,哎嘿,这不突破了自己的绘画瓶颈期吗?
水平越高,提升力度必定越慢、越长。但是,你要记住一点,这个“瓶颈期”一定是有尾巴的,只要一直画下去,就一定会提高。所以,进取心要有,但保持平常心更重要。”
“固守自封必然会陷入死循环,想要提高,就得去迎接挑战。”
我们平时画画的时候,一定会有些小习惯,比如,一下笔就画女孩子,画的人从来都是千人一面,画的构图永远是平视……等等,这些东西,或许并不算缺点,却会让我们不知不觉中变得“懒惰”。不自己去寻找突破口,就只能被动地等待瓶颈期的过去。
不同画法去画相同的东西
尝试用不同的画法去画同一种东西。或许你习惯用赛璐璐的手法去画插画,为什么不试一下水墨风呢?世上很多大师的风格都各有特点,试着去琢磨,去学习,你也会有更大的提升。
尝试更多的画面构成
尝试更多的画面构成。平视、俯视、仰视、鱼眼透视、上帝视角……你全部都练熟了吗?有没试过将同一样元素,用不同的视角去画?
换一种材料与技法
你可以换种画法、材料、观察方式,得到新的体验与感受,尝试平时不敢用的材料与技法。
以上素材来源于网络侵权即删
学画画,本就不是一件轻松的事情,所以大家要努力坚持,努力的去克服各种困难!加油吧~!
多媒体
2019-09-30 15:53:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
【推荐】板绘新手必学的女生头发上色 头发上色可谓是让无数绘画初学者无比头疼的问题。怎么上色才能让头发看起来干净利落,当下手时根本让人无从下手啊有木有!赶紧收藏起来吧:
1、涂上基础色。
2、使用正片叠底画阴影。
3、在盖一层一样的颜色,正片叠底。(画在2的图层上)
4、使用滤色,画上光感。
5、使用滤色在相对面上画薄薄的高光。
6、修改线稿的颜色与发色相融。
7、使用叠加 的效果让刘海有光感。
以上素材来源于网络,侵权即删。
文章由【学绘画,来艺学绘】收集整理,更多优质教程,请搜索官网查看。
多媒体
2019-09-28 16:14:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
【推荐】板绘过程中应该如何制造氛围? 画好人物氛围该怎么制造呢?今天为大家带来了一组制造氛围教程哦,有很多人都喜欢漫画吧,那么那些漫画世界里面的人物吧怎么这么梦幻呢是怎么画出来的呢?就让我们一起进入到今天的板绘教程中来吧:
制造氛围的三个要点:
一、总之先确定好一个光源。
二、总之要使用模糊来制造远近感。
三、总之要让画面有光感。
将这三个点作为要点,就能画出又氛围的画面。
1、定好一个光源:
2、使用发光效果和滤色效让画面更有光感(可在滤色效果上,从光源位置添加一层渐变):
3、感觉画面好像少了些什么的时候,可以加上少许文字。
以上素材来源于网络,侵权即删
文章由【学绘画,来艺学绘】收集整理,更多优质教程,请搜索官网查看。
多媒体
2019-09-28 16:08:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
「板绘教程」看完这几步你也能快速提取线稿 突然想上色百度一张线稿图?如何才能转成线稿呢?今天为大家带来了一组如何提取线稿的绘制教程哦,好啦就让我们一起进入到今天的线稿提取教程中来吧:
1、突然想上色,百度一张线稿,可是,线稿线面连着白色背景图层怎么办?要怎么把线稿拿出来?
2、按住【Ctrl+A】放开在按住【Ctrl+C】
3、按住蒙版,在按着【ctrl+V】然后关掉蒙版
4、新建图层在按住【Ctrl+Shift+i】再按住【Alt+delete】
以上素材来源于网络,侵权即删
文章从【学绘画,来艺学绘】收集整理,更多优质教程,请搜索官网查看。
多媒体
2019-09-27 17:17:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
【绘画】板绘小白如何快速画出山水画! !! 说起板绘那真的是种类画风繁多,还有脑洞突破天际的风格,下面介绍一下中国画中的山水系列,好啦就让我们一起进入到今天的漫画教程中来吧。
1、先来画河两边的岸:选用铅笔工具,颜色用黑色,在画板中随意涂一下,如下图:
然后用橡皮擦(橡皮擦设置结缕草,50%强度)擦出来河岸的样子,图层不透明度调整为75%,添加画纸质感fire,倍率300%,强度60.具体调整见下图。
效果如下图:
右岸新建图层,画法和左岸一样,如下图:
2、画山脉:同样用铅笔工具涂出山脉形状
然后还是用橡皮擦,擦擦擦,为了让山脉更逼真,山脚下我用模糊擦擦了一下,图层调整同上,得到下图:
另一座山画法同上,只是因为另一座山更远所以透明度调的要更低一些,我调的是50%画完效果如下:
以上素材来源于网络,侵权即删
文章从【学绘画,来艺学绘】收集整理,更多优质教程,请搜索官网查看。

多媒体
2019-09-25 16:23:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
保存我常用的ffmpeg命令.
都是从各处收集来的.除了常规操作,还有一些特殊的优化.
教程
官方文档
一个教程
一个转码的教程
基本操作
考虑到基于h264的mp4兼容性最好,例子中都用h264编码器吧. # 用h264编码器,参数默认 ffmpeg -i 输入视频 -vcodec h264 输出视频 # 用不同的预设参数(从快到慢有ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo),指定码率 ffmpeg -i 输入视频 -vcodec h264 -preset ultrafast -b:v 2000k 输出视频
Gif转mp4
来源 ffmpeg -i animated.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" video.mp4
解释: movflags – This option optimizes the structure of the MP4 file so the browser can load it as quickly as possible. pix_fmt – MP4 videos store pixels in different formats. We include this option to specify a specific format which has maximum compatibility across all browsers. vf – MP4 videos using H.264 need to have a dimensions that are divisible by 2. This option ensures that’s the case.
flv转mp4
来源 # 重新编码式 ffmpeg -i input.flv -c:v libx264 -crf 19 -strict experimental output.mp4 # 直接输出式 ffmpeg -i input.flv -codec copy output.mp4
解释: You must specify the video codec used. In your command you don't specify -vcodec or -c:v so ffmpeg uses the default codec for MP4 (mpeg4) which doesn't have very good compression efficiency. Try using libx264 instead and setting the CRF, which is the quality level (lower is better, default is 23, and sane values are between 18 and 28). Encoding with libx264 is kind of complex, so you should look up the H.264 encoding guide. You also need to specify -strict experimental otherwise you might get : " The encoder 'aac' is experimental but experimental codecs are not enabled, add '-strict -2' if you want to use it."
提取音频 ffmpeg -i input.flv -acodec libmp3lame output.mp3
多媒体
2019-09-25 09:33:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
由于工作需要,正在学习Voip语音方面的知识。原先以为电话两端声音有类似自然语言处理的过程,后来发现自己想多了。
ip的网络电话Voip是通过RTP协议传输通话两端的声音。我们可以通过wireshark抓包软件获取RTP传输的语音信息,并且可以将语音进行还原和播放。具体操作如下:
1. 打开wireshark软件,可以过滤出RTP数据包
2.打开wireshark分析语音工具,操作为电话---->RTP--->RTP流,
3. 根据目的地址和源地址,选择分析需要获取的RTP流,点击右下角分析

通过上述过程,可以还原刚刚的语音通话。
多媒体
2019-09-24 14:36:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
困惑1: 技术更新太快,什么都想学,可能什么也学不好?
但是对于我来说 可能说这句话不够资格,不管是自己相对所擅长的语言还是别的语言,都是半吊子。所以,还是要努力的多学一些,多学一点点也是进步。哪怕只是为了进入某个团队把技术当敲门砖,以后不一定做这个都行,但是一定要努力,如果努力了还是不行,那才有资格说一些话,那时最起码你要比现在强100倍。而且你可以看看你身边的人,有的人可能也是半吊子,也是没有精通的 只是什么都懂一些。但是人家就比你混的好。先追上这些人再说。

比较有感触的文章: https://www.cnblogs.com/vranger/p/3665579.html
多媒体
2019-09-23 20:13:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
[toc] 转自 https://blog.csdn.net/sw3300255/article/details/83782269(11.频域里的卷积——傅里叶变换的性质,傅里叶对,结论_3)
傅里叶变换
FFT
傅里叶变换的性质
让我们继续看看空间域和频域之间的关系。这是傅里叶变换的一些简单性质。我们从一个我们已经讨论过的问题开始。一切都是线性的因为我们只是做求和和乘法(如图),对吧?
我们刚才描述的是这个卷积。空间域的卷积就是频域的乘法,反之亦然,
一个有趣事情的是缩放。所以,如果我用一个常数a来缩放一个函数。我们这样想,假设a大于1,假设a是2, 这意味着当x = 1时,x = 2,它会收缩,对吧? 当你乘以一个大于1的数,
如果我有一个函数(如图1),现在发生的是这个值被移到这里(如图2),所以我实际上缩小了这个函数(图3),对吧?
123
所以当我缩小一个函数的时候它会摆动得更快,对吧?因为他们之前摆动得比较慢。如果我把它拉进去,它现在摆动得更快。结果是,我拉伸了傅里叶变换(如图)。这就是它的公式,1 / a乘以F (u / a)它有逆性质。就像高斯函数一样,对吧? 如果我让它变得更胖,我的傅立叶变换会变得更瘦。
最后一个看起来,我们不会使用这么多,但我希望你能看到这个(如图)。当你对一个函数求导时,这是一个n阶导数。
你将傅里叶变换F(u)乘以一个与频率成正比的函数(i2πu)^n,所以假设n = 1然后求一阶导数,对吧?
也就是说,你要把F (u)乘以u,这就意味着频率越高越明显。这就是求导时的结果。还记得我们加了噪声,高频噪声,然后求导,整个东西都爆炸了吗?那是因为你把它乘以,当你求导时,你乘以高频分量。
傅里叶对
如果你看一下我们前面提到过的Rick Szeliski的书,你可以看到一大堆傅里叶变换对。
例如,像这样绘制的脉冲具有1的傅里叶变换(如图)。就像我们说的那样,这是有道理的,因为当你对它进行卷积时,脉冲会返回原来的函数,所以你最好保持所有的频率。
同样地,我们说过高斯函数的傅里叶变换是另一个高斯函数(如图)。G(\sigma)等于1 /\sigma。空间上是胖高斯,频率上是瘦高斯。
但是看看这个。但是看看这个。如果我有一个盒子过滤器,它只是一个形状像盒子的过滤器,它会产生所谓的sinc函数。画在这里,
我们再仔细看看,Okay? 在这个空间域中(左图1),我们有一个方框滤波器这是sinc函数(右图2)。然后sinc(x) = sin(x)/x,我们可以这样想,如果你取x趋于0时的极限,你记得洛必达法则对顶部求导就是余弦,底部的导数就是0中的1,它是1,
x趋于0时的极限是1,在这里,
然后随着x变大,sin变弱这就是你在这里看到的。
换句话说, 如果我要用盒子滤波器卷积某些东西。我的频率会以某种奇怪的方式表现出来。你知道,我有这种很好的低通特性(如图) ,
但是接下来,我会有各种各样的其他频率(如图),这些频率会加重。如果你还记得,我们在引入过滤时很早就做到了这一点。
还记得吗,我们用一个盒子,和一个正方形做卷积? 我们说,天哪,这么丑吗?这就是为什么它很丑。看到这张图了吗?(如图) 你看它是怎么有这些小条纹的。我说过,当我们第一次做这个的时候,那是因为盒子不是光滑的当我们做傅里叶分析的时候我们会使它更正式。我遵守了我的诺言。 Okay?
当你把一个图像和那个小方块卷积的时候你会看到所有这些垃圾是因为频域中的这个振铃效应(如图)。
这就是为什么我们说,你应该做什么? 你应该应用一个高斯函数而不是一个盒子,它会形成一个漂亮的图像,你知道,一个漂亮的,平滑的图像。
因为在频域中,你会得到一个平滑的高斯分布(如图),
关于这些sinc函数还有一件事,好吗? 所以我们证明了盒子的傅立叶变换(左图1)是sinc(右图1)。
好吧,由于对称性,如果我在频率空间中有一个盒子(右图2),那将是空间域中的一个sinc(左图2)。
那么,如果我要采取一些函数,采用其傅立叶频谱并将其乘以这个方框,那会是什么样的呢? 好吧,我已经给你们看过了,对吧? 基本上,它有时被称为药盒,因为它是一个盒子。,但在2D中,这不是一个特定的宽度(左图),而是一个半径(右图),对吧?
因此,直径以外的所有内容都设置为0,内部的所有内容都保持不变。
如果你还记得我们得到的图片是这张丑陋的图片里面有很多铃声。 好吧,现在我们知道为什么了。 当您通过一个盒子乘以频率时,就好像您使用sinc函数将图像与其傅里叶对进行卷积。 因此,如果你拍摄这张漂亮的照片并用这个丑陋的野兽卷积,你会得到一些看起来像这样的东西(如图)。 这就是振铃的来源。 这就是为什么你永远不想只是削减高频,因为你实际上正在做的是用sinc函数卷积你的图像。
多媒体
2019-09-22 22:42:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
「推荐」小白到大神的动漫人物捏脸修炼手册
在这个大部分看脸的时代,五官辨识度是人第一记忆点,那么怎么才能画出不一样而且有特色的五官呢?
那么今天吃货木槿就在网络上收集整理了一些关于如何绘画人物五官的教程给大家,教你最简单的五官绘画技巧,教程非常简单,赶紧来看看叭:
一般定义上,人脸的五官指的是,眉、眼、耳、口、鼻、
眼睛的画法:
鼻子的画法:

耳朵的画法:

嘴巴的画法:


多媒体
2019-09-20 16:03:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
A comprehensive set of APIs for hardware accelerated video encode and decode on Windows and Linux.

NVIDIA GeForce Now is made possible by leveraging NVENC in the datacenter and streaming the result to end clients
Quick Links: Download GPU Support Matrix Using Video Codec SDK FFmpeg/libav Resources
NVEncode Features Performance
NVDecode Features Performance

The Video Codec SDK includes a complete set of APIs, samples and documentation for hardware accelerated video encode and decode on Windows and Linux.
The SDK consists of two hardware acceleration interfaces: NVENCODE API for video encode acceleration NVDECODE API for video decode acceleration (formerly called NVCUVID API)
NVIDIA GPUs contain one or more hardware-based decoder and encoder(s) (separate from the CUDA cores) which provides fully-accelerated hardware-based video decoding and encoding for several popular codecs. With decoding/encoding offloaded, the graphics engine and the CPU are free for other operations.
GPU hardware accelerator engines for video decoding (referred to as NVDEC ) and video encoding (referred to as NVENC ) support faster than real-time video processing which makes them suitable to be used for transcoding applications, in addition to video playback.

* Diagram represents support for the NVIDIA Turing GPU family
** 4:2:2 is not natively supported on HW
*** Support is codec dependent
Architecture x64 and ppc64le
Operating System Windows 7, 8, 10, Server 2008 R2, Server 2012, and Linux
Dependencies
Development Environment
NVENCODE API - NVIDIA Quadro, Tesla, GRID or GeForce products with Kepler, Maxwell, Pascal and Turing generation GPUs.
NVDECODE API - NVIDIA Quadro, Tesla, GRID or GeForce products with Fermi, Kepler, Maxwell, Pascal and Turing generation GPUs.
GPU Support Matrix
NVIDIA Linux display driver 418.30 or newer
NVIDIA Windows display driver 418.81 or newer
DirectX SDK (Windows only) CUDA 10.0 Toolkit Windows: Visual Studio 2010/2013/2015
Linux: gcc 4.8 or higher

What's new with Turing GPUs and Video Codec SDK 9.0 Up to 3x Decode throughput with multiple decoders on professional cards (Quadro & Tesla) Higher Quality Encoding - H.264 & H.265 (Refer to devblog for more details) Higher encoding efficiency (15% lower bitrate than Pascal) HEVC B-frames support HEVC 4:4:4 decoding support

Decode
For a full list of GPUs, encode formats and number of encoders and decoders , please refer to the: GPU Support Matrix .

Encode

Get NVIDIA Video Codec SDK

If you are looking to make use of the dedicated decoding/encoding hardware on your GPU in an existing application you can leverage the integration already available in the FFmpeg/libav . FFmpeg/libav should be used for evaluation or quick integration, but it may not provide control over every encoder parameter. NVDECODE and NVENCODE APIs should be used for low-level granular control over various encode/decode parameters and if you want to directly tap into the hardware decoder/encoder. This access is available through the Video Codec SDK.

For application users


Cross-platform solution to record, convert and stream audio and video. Includes NVIDIA Video Hardware Acceleration Hardware acceleration for most popular video framework Leverages FFmpeg’s Audio codec, stream muxing, and RTP protocols Available for Windows, Linux You can now use FFMPEG to accelerate video encoding and decoding using NVENC and NVDEC, respectively. Turing support coming soon

Learn more about FFMPEG
For application developers
Download Video Codec SDK 9.0

To download, you must be a member of NVIDIA Developer - DesignWorks .
By clicking the "Agree & Download" button below, you are confirming that you have read and agree to be bound by the SOFTWARE DEVELOPER KITS, SAMPLES AND TOOLS LICENSE AGREEMENT for use of the SDK package. The download will begin immediately after clicking on the "Agree & Download" button below.

All supported OS and architectures
Agree & Download

Partners
Read more
Read more
Read more
Read more
Read more
Read more
Read more
Read more \
Read more
Read more
Read more
Read more
Read more
Read more
Key Features of Video Codec SDK
NVENC - Hardware-Accelerated Video Encoding
NVIDIA GPUs - beginning with the Kepler generation - contain a hardware-based encoder (referred to as NVENC) which provides fully-accelerated hardware-based video encoding and is independent of graphics performance. With complete encoding (which is computationally complex) offloaded to NVENC, the graphics engine and the CPU are free for other operations. For example, in a game recording scenario, encoding being completely offloaded to NVENC makes the graphics engine bandwidth fully available for game rendering.

GPU H.264 (AVCHD) YUV 4:2:0 H.264 (AVCHD) YUV 4:4:4 H.264 (AVCHD) LOSSLESS H.265 (HEVC) YUV 4:2:0 H.265 (HEVC) YUV 4:4:4 H.265 (HEVC) LOSSLESS
MAX Color
MAX Res.
MAX Color
MAX Res.
MAX Color
MAX Res.
MAX Color
MAX Res.
MAX Color
MAX Res.
MAX Color
MAX Res.
Kepler Maxwell (1st Gen)* Maxwell (2nd Gen) Maxwell (GM206) Pascal Volta Turing
8-bit 8-bit 8-bit 8-bit 8-bit 8-bit 8-bit
4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096
N/A 8-bit 8-bit 8-bit 8-bit 8-bit 8-bit
N/A 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096
N/A 8-bit 8-bit 8-bit 8-bit 8-bit 8-bit
N/A 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096
N/A N/A 8-bit 8-bit 10-bit 10-bit 10-bit
N/A N/A 4096 x 4096 4096 x 4096 8192 x 8192** 8192 x 8192 8192 x 8192
N/A N/A N/A 8-bit 10-bit 10-bit 10-bit
N/A N/A N/A 4096 x 4096 8192 x 8192** 8192 x 8192 8192 x 8192
N/A N/A N/A 8-bit 10-bit 10-bit 10-bit
N/A N/A N/A 4096 x 4096 8192 x 8192** 8192 x 8192 8192 x 8192
* Except GM108 and GP108 (not supported)
** Except GP100 (is limited to 4K resolution)

For a full list of GPUs, encode formats and number of encoders and decoders , please refer to the: GPU Support Matrix .


Performance: 5X Increase over x264(CPU)
* Performance represents measured average performance and quality of different classes of videos (camcorder, gaming, screen, synthetic, and telepresence). Performance may vary based on OS and software versions, and motherboard configuration.
More Performance Results
Performance represents an approximation of max performance and may vary based on GPU clock speed, OS, software versions, and motherboard configuration.



NVDEC - Hardware-Accelerated Video Decoding
NVIDIA GPUs contain a hardware-based decoder (referred to as NVDEC) which provides fully-accelerated hardware-based video decoding for several popular codecs. With complete decoding offloaded to NVDEC the graphics engine and the CPU are free for other operations. NVDEC supports much faster than real-time decoding which makes it suitable to be used for transcoding applications, in addition to video playback applications.
NVDECODE API enables software developers to configure this dedicated hardware video decoder. This dedicated accelerator supports hardware-accelerated decoding of the following video codecs on Windows and Linux platforms: MPEG-2, VC-1, H.264 (AVCHD), H.265 (HEVC), VP8, VP9 (see table below for codec support for each GPU generation).

GPU *H.265 (HEVC) 4:4:4 H.265 (HEVC) 4:2:0 H.264 (AVCHD) 4:2:0 VP9 VP8 MPEG-2 VC-1
MAX Color
MAX Res.
MAX Color
MAX Res.
MAX Color
MAX Res.
MAX Color
MAX Res.
MAX Color
MAX Res.
MAX Color
MAX Res.
MAX Color
MAX Res.
Kepler Maxwell (1st Gen)* Maxwell (2nd Gen) Maxwell (GM206) Pascal Volta Turing
N/A N/A N/A N/A N/A N/A 12-bit
N/A N/A N/A N/A N/A N/A 8192 x 8192
N/A N/A N/A 10-bit 12-bit 12-bit 12-bit
N/A N/A N/A 4096 x 2304 8192 x 8192** 8192 x 8192 8192 x 8192
8-bit 8-bit 8-bit 8-bit 8-bit 8-bit 8-bit
4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096 4096 x 4096
N/A N/A N/A 8-bit 12-bit**** 12-bit 12-bit
N/A N/A N/A 4096 x 2304 8192 x 8192** 8192 x 8192 8192 x 8192
N/A N/A 8-bit 8-bit 8-bit 8-bit 8-bit
N/A N/A 4096 x 4096 4096 x 4096 4096 x 4096*** 4096 x 4096 4096 x 4096
8-bit 8-bit 8-bit 8-bit 8-bit 8-bit 8-bit
4080 x 4080 4080 x 4080 4080 x 4080 4080 x 4080 4080 x 4080 4080 x 4080 4080 x 4080
8-bit 8-bit 8-bit 8-bit 8-bit 8-bit 8-bit
2048 x 1024 2048 x 1024 2048 x 1024 2048 x 1024 2048 x 1024 2048 x 1024 2048 x 1024
* Except GM108 (not supported)
** Max resolution support is limited to selected Pascal chips
*** VP8 decode support is limited to selected Pascal chips
**** VP9 10/12 bit decode support is limited to select Pascal chips
For a full list of GPUs, decode formats and number of encoders and decoders , please see the available GPU Support Matrix .

Performance

For convenience, NVDECODE API documentation and sample applications are also included in the CUDA Toolkit , in addition to the Video Codec SDK.
Note: For Video Codec SDK 7.0 and later, NVCUVID has been renamed to NVDECODE API.

Developer Forums
Our forum community is where Developers can ask questions, share experiences and participate in discussions with NVIDIA and other experts in the field.
Check out the forums here .
Legacy Versions
Older legacy versions of NVENC SDK and Video Codec SDK are available here .
Additional Resources BLOG - Turing H.264 Video Encoding Speed and Quality BLOG - New GeForce-Optimized OBS and RTX Encoder Enables Pro-Quality Broadcasting on a Single PC SOFTWARE DEVELOPER KITS, SAMPLES AND TOOLS LICENSE AGREEMENT CUDA Toolkit FFmpeg/libav Video Test Sources ( YUV RAW 1080p Files - Heavy Hand video input ) Streamline live streaming system reference design
多媒体
2019-09-16 15:27:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 作 / 李哲文 文章来源于网络,如有侵权请告知,我们及时予以处理 投稿及建议:后台或邮箱发送给 阿文,免费为您上广告 图片仅作展示,无任何商业用途

‘P’、‘K’
‘P’
720P,1080P等,表示的是“视频像素的总行数”,比如720P表示视频有720行的像素,而1080P则表示视频总共有1080行像素数,1080P分辨率的摄像机通常像素数是1920*1080.‘P’本身表示的是“逐行扫描”,是Progressive的缩写,相对于隔行扫描。
‘K’
2K,4K等,表示的是“视频像素的总列数”,如4K,表示的是视频有4000列像素数,具体是3840*4096列。4K分辨率的摄像机通常像素数是3840*2160或4096*2160.
关注 户外商显广告机平台、 关注 户外老湿--哲文、
1080P
过去曾使用垂直分辨率来描述分辨率。因为1080P代表的是垂直分辨率。而几乎所有的高清显示屏的纵横比都是1.78:(即16*9,又名“宽屏”),这意味着其水平分辨率为1920像素(即1920*1080)。
因此,1080P并不等于“1K”。正如超高清相当于4K一样,1080P相当于2K。也就是说,1920*1080这一分辨率非常接近DCI所描述的2K标准。即便如此,大多数人往往不把1080P叫做2K,他们称之为1080P或全高清。
720P的像素数量大约为1080P的一半。
对比图片:
4K
从技术上讲,“4K”意味着水平分辨率为4096像素。这是数字电源倡导联盟所提出的分辨率。由于电源的纵横比不同,矩形屏幕的确切形状决定了电源的纵横比,所以其垂直分辨率并没有具体制定。
因此,严格从技术上来说,“4K”不是超高清,超高清的分辨率为3840*2160.两者之间的像素区别仅13%,基本上看不到多大差异。绝大多数人都更喜欢“4K”这一名称表示超高清。8K的道理跟4K一样。
对比图片:
多媒体
2019-09-16 15:12:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
1.第一步:抠图,找自动抠图的网站吧
https://www.remove.bg,把图片上传上去,会把背景图去掉,然后下载下来
2、第二步: 用photoshop打开,新建个图层,选择图层,然后(alt+delete) 填入前景色,
前景色选择白色。
3.第三步:图片大小调整,点击图像-图像大小,调整像素比如一寸是:358*441
4.第四步:图像存储为,设置图像清晰度,缩小大小,如果这样不行,可以通过
Ctrl+Alt+Shift+S,然后再如图选择来更改文件体积大小在20k以内即可。
多媒体
2019-09-14 22:03:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
原文地址: https://github.com/jackyxinli/cross-compile arm-none-eabi-gcc (ARM architecture,no vendor,not target an operating system,complies with the ARM EABI) 用于编译 ARM 架构的裸机系统(包括 ARM Linux 的 boot、kernel,不适用编译 Linux 应用 Application),一般适合 ARM7、Cortex-M 和 Cortex-R 内核的芯片使用,所以不支持那些跟操作系统关系密切的函数,比如fork(2),他使用的是 newlib 这个专用于嵌入式系统的C库。 arm-none-linux-gnueabi-gcc & arm-linux-gnu-gcc (ARM architecture, no vendor, creates binaries that run on the Linux operating system, and uses the GNU EABI) 主要用于基于ARM架构的Linux系统,可用于编译 ARM 架构的 u-boot、Linux内核、linux应用等。arm-none-linux-gnueabi基于GCC,使用Glibc库,经过 Codesourcery 公司优化过推出的编译器。arm-none-linux-gnueabi-xxx 交叉编译工具的浮点运算非常优秀。一般ARM9、ARM11、Cortex-A 内核,带有 Linux 操作系统的会用到。
Establish environment of cross compile on fedora 29 or upper # dnf install arm-none-eabi-gcc # dnf install arm-none-eabi-newlib # dnf install gcc-arm-linux-gnu # dnf install glibc-arm-linux-gnu # cd ~ # vim .bashrc C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/arm-linux-gnu/include export C_INCLUDE_PATH # source .bashrc # cd ~ # curl http://ffmpeg.org/releases/ffmpeg-4.1.4.tar.gz # tar -zxf ffmpeg-4.1.4.tar.gz # cd ffmpeg-4.1.4 # ./configure --prefix=/root/arm/ffmpeg --enable-gpl --enable-version3 --enable-nonfree --enable-cross-compile --arch=arm --target-os=linux --cross-prefix=arm-linux-gnu- --cc=arm-linux-gnu-gcc --enable-pthreads --disable-doc --disable-debug --disable-x86asm --disable-static --enable-shared
Establish environment of cross compile on ubuntu 18.04 or upper # apt install gcc-arm-none-eabi # apt install arm-linux-gnueabi # apt install arm-linux-gnueabihf # cd ~ # curl http://ffmpeg.org/releases/ffmpeg-4.1.4.tar.gz # tar -zxf ffmpeg-4.1.4.tar.gz # cd ffmpeg-4.1.4 # ./configure --prefix=/root/arm/ffmpeg --enable-gpl --enable-version3 --enable-nonfree --enable-cross-compile --arch=arm --target-os=linux --cross-prefix=arm-linux-gnueabihf- --cc=arm-linux-gnueabihf-gcc --enable-pthreads --disable-doc --disable-debug --disable-x86asm --disable-static --enable-shared
多媒体
2019-07-30 16:55:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
TheBrain 可以让你捕捉到你处理的文件背后的想法,并更有效地组织信息。同时能够将所有信息通过一个又一个的节点进行联系,最终形成一个杂而不乱的网状结构。从头开始设计,让您捕获您的想法和信息在一个网络的联想,匹配您的思维方式。 >>最新版TheBrain体验下载
TheBrain功能亮点: 数字思维 整合分散的资源 随时访问 快速搜索 强大的文档管理功能 一目了然的图形
TheBrain 公司非常喜欢不定期的举行 网络研讨会 ,也可以称之为网络课程,专门由其公司的高层技术人员为大家带来有主题的讨论会。下面小编给大家整理了2019最新的网络研讨会视频合集,希望大家能够更加了解TheBrain的实用性,帮助大家最大程度的开发我们的大脑思维。
①TheBrain 202网络研讨会:改善和进化你的大脑
【点击查看完整视频】

具体主题包括:
改变思想关系 创建子类别和干预思想 大量链接,取消链接,忘记和删除想法 复制和粘贴思想 使用多个大脑 创建特定的思想名称和思想世系 为其他上下文添加图标和思想类型

②【TheBrain网络研讨会】视觉故事——用作者的大脑释放你的创造力
【点击查看完整视频】

具体主题包括: 捕捉创意并策划创意内容 可视化故事元素和参考 通过视觉头脑风暴克服作家的障碍 为编写项目创建研究指南 管理多个版本的文件并导出到Word

③【TheBrain网络研讨会】在TeamBrain中共享多人力量
【点击查看完整视频】

具体主题包括: 通过安全的云服务同步大脑,实现多台机器访问或许多用户 在线为大量受众创建和发布您的大脑 管理多个用户的大脑,添加组成员和跟踪更改 可视化业务流程和想法,以便每个人都能看到关键策略 通过集体知识网络节省时间并减少会议

④【TheBrain网络研讨会】在Mac、iPhone和iPad上进行大图组织和任务管理
【点击查看完整视频】

具体主题包括: 可视化关键想法和项目 组织和相互关联的文件和网页 跨平台工作,并在多台机器上同步 在你的iPhone和iPad上创造新的大脑 通过集体知识网络节省时间并减少会议 集成了Apple Mail、地址簿和iCal

⑤【TheBrain网络研讨会】使用TheBrain如何更加直观的管理文件
【点击查看完整视频】

具体主题包括: 将文件、网页和文件夹整合到你的大脑中 跟踪和附加多个版本的文档并将其保存到您的大脑中 交叉引用和链接相关文档,便于发现 把文件从你的大脑中移进移出,做笔记 根据概念和文件类型搜索和过滤信息

-- 持续更新中 --
多媒体
2019-07-15 15:32:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
adobe官网上下载flash player:
https://get.adobe.com/cn/flashplayer/otherversions/

下载后解压:
tar xf flash_player_npapi_linux.x86_64.tar.gz

将解压的 usr/目录文件拷贝到 /usr下:
cp -r usr/* /usr

再将libflashplayer.so 拷贝到浏览器插件的目录下:
cp libflashplayer.so /usr/lib/mozilla/plugins/

重新打开Firefox,播放视频:
多媒体
2019-09-09 16:30:00
「深度学习福利」大神带你进阶工程师,立即查看>>>

以上这些需求简直就是设计师的噩梦!
设计入行门槛高,且各人审美标准差异较大,在设计中普遍存在着一些共同性的难题。比如说设计时才发现素材不够、没有统一标准导致设计结果客户不满意,特别是有些“高级”的设计根本不能引起消费者共鸣等,都为日常的设计工作带来了不小的挑战。
大量设计所需的人力成本、机械重复的操作成本、反复修改的沟通成本、购买字体和素材版权成本等各种费用的消耗,无形之中也增加了企业的负担,同时,也带来一些侵权问题和风险。
日前,京东云联合京东零售用户体验设计部,推出专业的智能设计服务,为解决企业运营过程中设计效率、品质、一致性问题提供解决方案。整合京东自身在设计、大数据、AI技术等领域的专业能力,搭建智能设计引擎,帮助企业提升效率、节省成本、优化输出,并为数据化投放与运营提供能力支持。
用户将需要解析的内容传入,由智能设计引擎对输入内容进行识别与分析,之后通过智能设计处理器进行处理,完成用户需要的操作,最终产出设计结果。替代设计师人工设计,手动操作,将设计结果规范化、精细化、自动化,稳定输出。 当前,智能设计服务在京东云官网以API接口形式,提供服务,快来看看有哪些实用功能,能够帮助企业快速提高设计效率,降低设计成本吧!
智能抠图服务是为图片主体抠除背景的智能服务。基于机器学习、图像智能识别技术,可大幅度提升图像处理效率,降低人工成本。
1、智能抠图功能特点
通过机器智能识别图像,不用人工进行加工处理,只需将需要处理的图片上传,极速自动输出无背景抠图结果。划分区域,零门槛、低成本,无需使用设计软件,抠图成功率高,基于京东海量商品图片训练机器不断学习优化,整体抠图尤其针对电商商品图片抠图成功率行业领先。
2、智能抠图应用场景
不论是自己拍摄还是从网上寻找素材,都需要进行一定的处理,才可以使用到图片设计当中。使用智能抠图功能,可以轻松快捷地将图片主体与背景分离,生成透明底图片。同时,可针对特定场景进行图片优化,需根据业务情况更换背景、强调重点、区分层级,可通过智能抠图服务将图片主体与背景分离,由机器批量快速地完成原始素材的处理。
智能抠图服务目前服务于京东SKU图库,对京东商品库进⾏批量处理,建⽴商品透明底图素材池,⽬前已累计商品素材1600+万张,供京东各业务使用。

智能配色服务是由单个配色方案智能延展为多个配色结果的实用功能。 基于图像智能识别技术,对图像颜色进行精准识别和替换,可用性强,可快速衍生多样的设计风格,大大拓展图片的使用范围,有效降低人工制作成本。
1、智能配色产品优势
对设计对象进行智能颜色识别、灰度计算,快速输出大批量不同风格的配色结果。 简单易用 :以机器工作代替人力,精准高效、方便易用。 海量方案 :经过素材的灵活组合,填色结果的数量是人工制作所远不能及的。 可用性强 :系统提前预设配色方案,已历经多次演算优化,结果美观可靠。 多场景应用 :覆盖电商、零售、物流、媒体等多种业务场景。 支持定制化 :可根据用户需求定制化开发。
2、智能配色应用场景
一张图片可延展出丰富的配色结果,用户可根据图片要传递的内容,挑选最恰当的配色结果。无需人工试色,直观感受不同配色效果,辅助决策,选出最优结果。

智能配色功能可完美划分填色区域,支持自定义图片配色,可满足用户对图片进行特定颜色的批量调整,以使所有图片配色统一。
风格识别服务是能够读取图片信息,实现按照风格进行智能归类管理的功能。 由深度学习引擎打造,通过构建样本数据集训练机器,形成风格预测模型,根据模型,可从图片信息识别出风格特征元素,自动判别图片设计风格。
1、风格识别功能特点
识别并解析用户传输的任意图片,自动划分区域,根据风格预测模型智能识别图片风格特征元素。根据特征元素,将图片按风格分类,将图片的设计风格返回给用户。 识别结果准确度高,基于京东海量图片数据,针对电商场景下的广告图数据进行测试,风格预测结果的准确率已超过83%。图片识别速度快,任意样式无差别准确识别,即时返回识别结果,代替人工查看样式、判断思考过程,摒除主观判断差异,高效统一。
2、风格识别应用场景
最大的应用场景为图片的智能管理,和与用户智能匹配。可应用于图片的智能读取及标签化分类,轻松实现批量管理,无需进行人工分类。

多媒体
2019-09-06 14:01:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
前言
个人比较喜欢momentum插件的图片壁纸,比较清爽的世界各地的风景画吧。这个插件的图片来源也是来源于其他网站Instagram、Flickr、unsplash、500px等。(不知道怎么弄过来的)
windows本地图片地址
windows如果安装了chrome的momentum插件,本地文件夹缓存数据,例如: C:
多媒体
2019-08-29 23:49:00
「深度学习福利」大神带你进阶工程师,立即查看>>>

断点设计、双色搭配、高光设置、填色错位
渐变色使用、半透明装饰、统一的阴影

拟物图标icon手机应用3D仿物图标APP2.5D设计UI素材PSD源文件图片
多媒体
2019-08-27 14:46:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
标定 import cv2 import numpy as np import glob criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) w,h = 9,6 objp = np.zeros((w * h, 3), np.float32) objp[:, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2) obj_points = [] img_points = [] images = glob.glob('待标定图像') for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) size = gray.shape[::-1] ret, corners = cv2.findChessboardCorners(gray, (w, h), None) if ret == True: cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) obj_points.append(objp) img_points.append(corners) cv2.drawChessboardCorners(img, (w, h), corners, ret) cv2.imwrite('标定图.png', img) ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None) dist = np.delete(dist, [4]) #当畸变不夸张时舍去K3
矫正 img2 = cv2.imread('待矫正图') h, w = img2.shape[:2] newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h)) dst = cv2.undistort(img2, mtx, dist, None, newcameramtx) cv2.imwrite('矫正图.png', dst)
多媒体
2019-08-15 16:10:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
之前做个设计,现在从事IT,脑子里面关于RGB,RGBA,CMY,CMYK,YUV,但是具体理论还是不扎实。若干年前之前写过《 水煮RGB与CMYK色彩模型—色彩与光学相关物理理论浅叙 》《 三色视者与四色视者身后的理论基础:色彩原理 》
光学三原色与印刷三间色
光学的三原色 : 红(Red)、绿(Green)、蓝(Blue) (RGB)。
印刷的三原色 : 青(Cyan)、品红(Magenta)、黄(Yellow) (CMYK)
印刷色是光照射在印刷物上, 然后折射到人眼的光的合成,所以印刷色会比光学暗淡,因为印刷色是经过印刷物过滤过光合成的,自然会比较相对暗淡。
C(100) +M(100) +Y(100) = 黑色(100,100,100)
可见黑色就是青色、品与黄色之和,但是这三种颜色混成的黑色不够纯,所以印刷学就引进了K(Black)黑色,因为B已经被Blue占用,所以黑色就只好用引文字母黑色的最后一个字母K,所以:
C(100) +M(100) +Y(100) + K(100) 等价于 C(0) +M(0) + Y(0) + K(100) = 黑色
光学三原色如何得到白色, 配色如下:
R(0) + G(0) + B(0)+A(255) = C(0) +M(0) + Y(0) + K(100) = 黑色
联想下,是不是可见黑色就是没有颜色(0,0,0)?
我们显示屏一般采用RGB,印刷采用CMY。RGB/CMY色彩模型是通过不同量的(红/绿/蓝)||(青/品红/黄)来描述一个颜色的,对人类来说很不直观,难以理解。他们对机器很友好的色彩模式,但并不够人性化,难以直观理解,因为我们对色彩的认识往往是:什么颜色?鲜艳不鲜艳?亮还是暗?
基于RGB改进的HSL/HSV色彩模型
HSL 模式和 HSB ( HSV ) 都是基于 RGB 的,是作为一个更方便友好的方法创建出来的 。HSB和HSV是是一样的,只是叫法不一样而已 HSL :色相H(Hue) ,饱和度S(Saturation),亮度L(Lightness) HSB :色相H(Hue) ,饱和度S(Saturation),明度B(Brightness)
色相H(Hue) 控制颜色种类,取值0-360°的圆心角。需要记住色相环上的六大主色: 红黄绿青蓝洋红 (即RGB夹CMY呈60°分布)用作基本参照
饱和度S(Saturation) 控制颜色的纯度。取值0-100%。数值越大,颜色中的灰色越少,颜色越鲜艳,呈现一种从灰度到纯色的变化
亮度L(Lightness) 和 明度B(Brightness) 控制色彩的明暗变化,取值0-100%。
HSB与HSB其中的S与L有着不同的表述。这里暂且忽略,推荐阅读: 色彩空间中的 HSL、HSV、HSB 有什么区别- AK23的回答 - 知乎
Lab颜色模型
Lab颜色模型是由国际照明委员会 (CIE:International Commission on illumination) 制定的一种色彩模式。 L*代表明度,取值0~100 a*代表从绿色到红色的分量 ,取值-128~127 b*代表从蓝色到黄色的分量,取值-128~127
这样规定是根据人类的视觉原理,灵长类动物的视觉都有两条通道:红绿通道和蓝黄通道,大多数动物最多只有一条通道,如果有人缺失其中一条,就是我们所说的色盲。
其实,我们生活中所说的颜色和光谱中可见光的颜色并不是严格对等的。 实际上,存在两种颜色的定义 : 自然界真实存在的颜色 :严格对应波长,实际上所谓的不同的颜色就是可见光电磁波的不同波长(或者能量不同)的光子。比如波长为550nm的光子、波长为700 nm的光子... 人眼感知的颜色 :人眼对整个可见光谱的感知。因为人眼视网膜上,主要负责感知色彩的视锥细胞对不同波长的光子的感知并不相同,存在一个相应的范围
而人眼对不同波长的感知能力可以用下图中的白色曲线来表示。白线对应的值越高,表示人眼对此波段的光子的感知越灵敏。人眼把S那条线感受到的光子都认知为蓝色、把M那天线的认知为绿色、把L那天线对应的认知为红色。
实际上,上述的三种颜色:蓝、绿和红色(RGB)正是我们所知道的三原色。所以,事实上,你只能看到三种颜色:蓝绿红!等等……事实不是这样啊!我们的世界明明丰富多次啊??你怎么在这里瞎扯?其实,你看到的多种多样的颜色是这三种颜色组合在一起的结果。这三种颜色好比一个三维空间里的三个坐标,你把他们不同程度的组合起来,就可以形成各种各样的颜色。实际上,他们形成了一个3D的色彩空间,如下图,空间中每一个点都代表了一种颜色。
所以你看到的颜色其实就是人眼在对蓝绿红这三种光子的测量,然后线性的叠加而已!其实我们的RGB显示器就是运用了这个原理,显示出不同的色彩。所以 ,很多颜色并不是真正的一个颜色而已,它代表的是这个物体发出的光中,蓝绿红这三种光的相对强度的组合 !! 这些美丽的颜色中很大一部分其实只是你的脑补而已…… [不过,因为人眼视锥细胞的响应也存在饱和,也就是说蓝、绿和红不可能无限的亮,因此,人类的感知只是这个三维空间里的一个有限区域 。这也是CIE定义出他们最有名的CIE色表的来源。因为人类对色彩的感知是有限的,且我们实际上对实际的光谱更感兴趣,所以,根据人眼对色彩的响应曲线,我们可以把上面的三维空间变换到二维(如下图)
而这二维的平面涵盖了人眼能看到的所有颜色(注意,实际上上述的三维色彩空间里有很大一部分是人眼无法识别的颜色,因为人眼视锥细胞的感光能力是有限的!),于是就形成了下面的CIE图,此图是1976年的修改标准,该图最早由1931年提出。

而,通过数学运算,不难算出真实光谱,比如450nm的光应该什么颜色的。你只需要把450nm处三种颜色的视锥细胞的响应叠加起来就行了。通过这样的方法,你就可以计算出一条曲线,它可以近似代表自然界中真实的色彩。此外,你还可以计算出色温曲线。如果你还记得黑体这个概念的话,不同温度会给出不同的能谱分布,如下图,不同的能谱分布中,蓝、绿和红色的相对强度不同。
那么同样通过数学的运算,你可以计算出不同温度黑体在人眼中所反映出的“颜色”。就是图中间的那条曲线。太阳的温度是~6000K,于是我们可以对应出来,太阳是白色(偏一点点黄)。]然而,还需要提到的是,上面说的是物体发出的光,比如太阳(黄白色),还有你的显示器。那么绿叶的颜色又是怎么回事?白纸呢?白种人为什么那么白?黑人为什么那么黑?因为他们不发光。所以,其实他们的颜色只是他们反射的光中蓝绿红这三种光的相对强度的组合!!因此,对于反光的物体来说,光源的颜色覆盖很重要。这也是为什么我们使用日光灯或者白光灯的原因。试想一下,如果你用绿光灯,你还能看到丰富多彩的衣服和图画吗?值得一提的是,汉语里的紫色其实是一个比较模糊的概念,既可以对英语英语里的violet,也可以是purple。严格来说,violet更接近比蓝波波长更短的颜色,也就是红和绿都很少,而蓝色也很弱的情形。相当于黑中加了点蓝的感觉。而紫色则是纯粹的脑补大红+大蓝而已。不管则样,紫色并不是真实的颜色。那么violet呢?其实它也并不是真实的,我们再来看一副更精确的视锥细胞响应曲线
或者为了更加严谨,我们来看看论文里实际的测量曲线:
注意到了吗?实际上在比蓝光中较短的波段红色视锥细胞的响应也比较突出,大概是0.1,而蓝色大概是0.7-0.8。因此,你看到的violet也是蓝+红组合的结果。
一句话总结,我们大致可以理解为, 颜色是自然界的可见光波段的光谱在人眼中的一个线性投影。我们可以更具CIE,把人眼中看到的“颜色”,还原到自然界“真实的颜色” 。

自然界中任何一点色都可以在Lab空间中表达出来,它的色彩空间比RGB空间还要大( 有毛用 ?超过了RGB色域屏幕显示不了,超过了CMYK的色域打印不了,超过了视觉色域看都看不了!高精度下lab偶尔可以作为颜色模式的中间标尺,但是这和你一点关系都没有。这纯粹是数学公式定义的结果——色域很大纯粹是因为定义范围内有许多多余的颜色)。不过对PS用户来说:LAB最大的优势就是调色,最常用的也是调色。明度和色彩信息因为是分离的,可以允许做出更多的操作,更精准的调整。也可以通简单的调整就出做一些别的模式非常复杂的操作才能达到的效果。比如照片过暴导致高光细节丢失严重,就可以用LAB修补高光部分的色彩信息。
这种模式是以数字化方式来描述人的视觉感应, 与设备无关,所以它弥补了RGB和CMYK模式必须依赖于设备色彩特性的不足。由于Lab的色彩空间要比RGB模式和CMYK模式的色彩空间大。
注:
Catmull和Smith在1971至1972年间提出了这个不可或缺的alpha数值,使得alpha渲染和alpha合成变得可能。提出者以alpha来命名是源于经典的线性插值方程αA + (1-α)B所用的就是这个希腊字母。PNG是一种使用RGBA的图像格式。
注:一般两个色彩空间,找一个变换矩阵,可以快速转换。
原文链接: 色彩空间RGB/CMYK/HSL/HSB/HSV/Lab/YUV基础理论及转换方法:RGB与YUV - 计算机视觉与计算机图形学的图像处理所涉及的基础理论知识 - 周陆军的个人网站 ,原文阅读体验可能更好,文章更新只在源站进行,如有不妥之处,请留言告知,多谢

参考文章:
色彩空间表示与转换 https://zhuanlan.zhihu.com/p/24281841
多媒体
2019-08-11 20:14:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
准备Raspbmc
为了安装Raspbmc,需要准备几件东西。第一件是一张新的SD卡——之前的那张要用在普通环境下;SD卡事实上就是树莓派的硬盘,所以如果过度写入,就只能重新刷镜像才能修复了,大概就等同于重装系统。没必要用一张新的SD卡,但是推荐用新的。一张microSD再加上一个SD卡套也是可以的。
无论你选择哪种方案,卡都要先格式化,于是在进行下一步前,把卡插到读卡器中,连接到你的PC上。
然后,下载 Raspbmc安装器 。下载完成后,解压缩并运行installer.exe文件。
你的SD卡应该会在安装窗口中显示出来,选中SD卡那一项前面的小方格,然后点击安装,软件就会把Raspbmc安装到SD卡上面。当“恭喜”信息出现的时候,就可以把卡拔下来,插到你的树莓派上面去了。
设置Raspbmc

把安装有Raspbmc的SD装到树莓派里,打开设备,确保设备和外网是连通的,因为在安装过程中,还有一部分数据要从网上下载,所以说连网是必须的。
可以用树莓派上的XBMC干什么
Raspbmc是流行的媒体中心软件XBMC移植到树莓派上的产物。所以用户界面喝功能大体上是相同的。
图片,视频以及音乐都有各自的菜单,有小软件可以收到三个地方的天气情况。媒体源需要手动添加,可以用插件管理器安装插件,有很多插件可供选择。
多媒体
2019-06-03 15:18:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
windows7 windows10专业版非常纯净的,是从官网下载的
网盘只有win7
微云盘有win7也有win10

我的百度网盘链接: https://pan.baidu.com/s/10EwNm6dp0sBDbqY7ktXMaQ 提取码: 2evk
或者去我的微云里下载,这个是不需要提取码的。win7链接:https://share.weiyun.com/5LXxdYt

win10链接:https://share.weiyun.com/5BsNDaa
---------------------
作者:WinkJie
来源:CSDN
原文:https://blog.csdn.net/qq_36662459/article/details/90697765
版权声明:本文为博主原创文章,转载请附上博文链接!
多媒体
2019-05-30 16:44:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
这个社会,只要你说你是搞技术的,领导就以为你啥技术都会!我就纳闷,为啥领导你病了,会找内科医生去看病,不会找错外科医生?为啥领导你小孩病了,你会找妇幼医院,不会找错兽医院??!
言归正传!
收到命令,要把MP4视频文件刻录成DVD可播放文件!
网上的转码以及刻录软件很多只负责生成VOB文件,到完成任务为止未找到自动生成并刻录DVD的软件或方法,如有大虾知道请赐教!

详细方法

步骤一
把MP4文件通过格式工厂转换为VOB文件
步骤二
DVD所需的IFO、BUP文件需要另外的软件 IfoEdit
下载: http://www.ifoedit.com/index.html
软件使用方法:
1.首先将vob文件名改为常规DVD文件格式,即
VST_01_1.VOB
VST_01_2.VOB
VST_01_3.VOB
......
依此而下
2.打开IfoEdit程序
3.点开界面下方第一排第四个按钮create IFOs(创建IFOs)
4.在1st VOB of 的地方打开VOB文件
如果有多个VOB文件时,选择最后一个
5.勾选same as source,然后点击ok
6.正在生成
7.回到VOB所在的文件夹,IFO、BUP文件已经生成好了。
步骤三
放入刻录光盘,双击光盘盘符,进入到虚拟盘,使用windows自带的刻录软件,把上述生成的所有ifo、bup、vob文件拷贝到这里,最后右键刻录到光盘,完成

Reference:
https://zhidao.baidu.com/question/149893015.html
多媒体
2019-05-27 19:33:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
今天发现一个超级好用,并且免费的logo创建器, launchaco.com ,之前用过 shapefactory.co ,也很好用,但是贵的令人发指,一个做好的logo,需要44美金。而今天发现了 launchaco.com ,感觉发现了一块宝藏,忍不住想分享。好了,现在来复盘一下整个使用流程。
以我最近正在开发的产品: 找主机 zhaozhuji.info为例
开始
打开 launchaco.com 官网,选择 logo 菜单,点击 Create Your Logo for Free
产品取名字
注意只支持英文字母,不支持中文,这是唯一的瑕疵。而本身这个产品是建立在人工智能上的,中文不仅字体不支持,也不支持含义联想。
选字体
没三种选一种字体,会让你选择四五次,它是期望发现你的字体爱好!
选择主题色
下图中列出了6中不同的主题色,每一种都代表不同的含义,并且明确标出了,请注意看图的下面。
这里我选择第一种, Friendly, Loyal, & Strong ,代表着友好、尊贵、强大。
每种主题色都给你配置好了3种色调,并且标明了适用的含义,是不是很方便啦!
这里我们选择第三种: Peaceful, Limitless, Tranquil, & Friendly
选择logo
选择3个你喜欢的logo!
说真的,这个网站的logo真的超级棒,每个我都很喜欢!
选择搭配
最后,系统会根据你的选择,给出一系列智能搭配。
保存
搭配中,随便选一个,然后编辑,然后点击右上角保存!
下载
右上角箭头下载后,你会得到png和svg很多资源,想要的都有了,如下图:
总结
有没有感觉很方便?关键是免费啊,基本类似的logo maker都收费,难得发现个免费的。后续我会继续发布有助于独立开发者产品开发的工具,关注我公众号及时提醒。
多媒体
2019-05-27 16:22:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
>**简评:**渐变是通过两种或多种不同的色彩来绘制一个元素,同时在颜色的交界处进行衰减变化的一种设计。从拟物到扁平再到渐变,人们慢慢发现它能创造出从未有过的一种色彩感觉 —— 独特、现代和清爽。(本文译者 @Aceyclee )
很长一段时间以来,设计界都不怎么待见「渐变」,这还得拜 90 年代的 PowerPoint 所赐,毕竟那时候的渐变是这样的:
然而时过境迁,今天你打开 Dribbble 或者 Behance,可能会看到不少使用渐变的设计。本文将会分享如何在设计中使用「渐变」的实用技巧。
▎为什么我们突然爱上了渐变?
想回答这个问题,我们需要重返 2014。
2014 年是扁平设计流行的元年。这一年,Google 发布了 Material Design,Apple 也用扁平 UI 更新了 macOS。那年的扁平设计让人感到兴奋,特别是和拟物设计对比的时候。
但是扁平设计的局限性也是显而易见的,其中最大的一个局限是 —— 设计师能够使用的颜色和样式大大减少,几乎不到 15 种颜色可用于扁平设计。
由此,设计师们开始尝试「渐变」: 它给设计师带来了更大的创作自由。扁平设计中单一的颜色扼杀了设计的潜力,而渐变为无限可能打开了大门。通过混合颜色的手段,设计师们可以创造出更丰富的视觉样式。 渐变还给设计引入了深度和维度,解决了扁平设计中一切都「太平」了的问题。
▎渐变让人惊喜
比如说,渐变能做出更大胆的表达。
渐变创造出了一种意想不到的效果,即使像应用图标这样微小的元素,也别有一番风味:
又或者,渐变能突出某些元素。
一个好的用户体验,往往能引导用户完成产品流程,而精心的设计有助于让用户下意识地进行下一步。比方说让页面某些部分视觉效果更强烈,从而让用户更关注这部分。
👇下面是 Mixpanel 的主页,插图是主页的一大元素,而渐变的背景则引导了用户去关注镇部分。
▎六种创造渐变的技巧
1. 让我们先看看渐变的基础类型
渐变有几种基础类型,他们都会有一个中心起点,颜色从这里开始,然后逐渐融入其他颜色。
a. 线性
线性渐变是一种依直线过渡的色带,颜色从一种颜色平滑过渡到下一种。
b. 径向
径向渐变是从中心点开始往外辐射,设计师可以指定中心点的位置和渐变的大小。
c. 锥形渐变
如下图,你可以在 Adobe Illustrator 中创建锥形渐变
2. 注意渐变颜色的选取
不是所有的颜色都能很好地相互配合,如果用互补色进行渐变,看起来就不是很好:
红色到绿色的渐变,看起来脏兮兮的:
创建渐变的时候,最好使用相近的颜色:
或者相同颜色的不同深度:
3. 渐变过程中注意平滑过渡
理想情况下,不应该让用户注意到一种颜色流入到另一种颜色中,颜色的过渡应该非常顺畅。
👇下面这个是反例,你能很明显地看到分隔两种颜色的色带,这就给人一种很突兀的过渡:
平滑应该是这样的:
4. 情绪的传达
颜色能唤起情绪的反应,我们可以利用这个属性,在更深的层次上和用户进行联系。
仔细思考你希望用户与产品互动时感受到什么。
例如,在一种比较高能量的氛围中,可以采用红橙渐变:
而在轻松的氛围,不妨试试蓝色渐变:
5. 不要忘记颜色对比
无论何时都要注意设计的可读性,而这就是对比的功用。

6. 一些趁手的工具
工欲善其事必先利其器,除了  Adobe Illustrator ,还有其他工具可以用于创建渐变效果: https://uxpro.cc/toolbox/visual-design/colors/ ,这里就不一一介绍了。
> 原文链接: Gradients in UI Design > 推荐阅读: Chrome 小恐龙背后的故事 | 设计师专访
多媒体
2019-05-21 14:42:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
QTcreator官网。专注于界面开发: qt creator 相关文档,做好qt简简单单。
http://www.qter.org/portal.php?mod=list&catid=18
多媒体
2019-05-20 10:21:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
打开菜单中工具--->页面信息---->媒体
多媒体
2019-07-15 15:00:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
近年来 思维导图 在工作与生活中的运用十分的火爆,它是一种能帮助我们学习和记忆的工具。
曾经有人做过一项调查,发现思维导图使用领域前10名分别是:待办事宜、准备演示、做笔记、解决问题、项目计划、做决定、知识管理、项目管理、个人思考以及写作,其中近一半的人认为思维导图对自己最大的帮助就是理清思路。
在思维导图中,不仅仅只有文字,图片、链接、标注、有趣的样式等等都能够加强我们的记忆。对于人的大脑,我们一升大概只能运用5-10%的大脑潜能。而思维导图是一种较为形象、具体、直观的图,对比抽象的语言,它更易于理解和记忆。
目前,市场上思维导图工具非常丰富,小编经过整理发现国内非常受欢迎的一款是 XMind,而对于国外软件, TheBrain 则是非常良心的推荐。
重点来啦!TheBrain vs XMind ,哪款才是你的菜?
★界面风格
对于一部分人来说,外表的赏心悦目往往更能引发对工作的兴趣和动力,一张有趣、色彩丰富的思维导图往往更能受到我们的喜爱。对于大多数国人来说, XMind 或许更符合我们的审美观, TheBrain 简单单调的界面或许会让人感到乏味。
TheBrain 默认的背景是深蓝色的,仿佛是无限的宇宙,又或者是一个人闭上眼睛后看到深邃的脑海。 XMind 则拥有多种配色组合和丰富的主题元素。
TheBrain
XMind

★ 产品属性
虽然两款都是思维导图工具,但其实两者也具有自己的特色: XMind是平面的 树状图形 ,TheBrain更像立体的 动态网络图 。 XMind是从 中心发散 的,TheBrain几乎是 去中心化 的。
XMind更倾向于树状结构,当思想过多时就会使图形变得很复杂,反而会造成困扰。尽管跨组织之间的链接现在也能够实现,但并不直观,在操作上比TheBrain更为复杂,返回父级时需一级一级的进行。 >>下载体验XMind最新版
XMind效果示例图
TheBrain能够管理各个节点的布局,还有节点快速搜索,可以很轻松地联系到思维导图里的任何节点。同时,TheBrain能够管理节点的布局和节点的隐藏,这样在做每一个子任务的时候,都能专注于这一个子任务,不会在视觉上陷入其他的任务视图。 >>下载体验TheBrain最新版
TheBrain效果图

★ 适用场景
TheBrain 无论界面还是功能都非常简单,每个“想法”的切换都以平滑的动态效果进行不用担心想法过多后反而影响思绪,更加适用于个人的知识整理、数据的整理、复杂的关系网分析、庞大的族谱、图书整理等等内容繁杂、思维跳跃的工作。
XMind 无论是丰富的主题元素、多元的配色组合,还是演示、幻灯片模式的展现,以及输出的图好比组织有序的“知识点”,可以很容易阅读,都表明它更加的适合工作汇报、方案策划、idea共享、事件分析等等。

★ 案例对比
这里以 个人的大脑思维整理 为例, TheBrain 可以无限的点击标签进入子级,同时右侧的备注内容非常清晰; XMind 则近乎是一张平面的图片,虽然同样能跳转子级,但按钮不够明显,有着明显的区别。
TheBrain示例:
XMind示例:

★适用平台
两者都适用于 Windows 平台和 MacOS 平台,同时对于手机端 iOS和Android平台也同步推出,随时随地都可以进行思想的交流和工作的整理。


你是不是思维导图的忠实fans呢?
你觉得哪款工具更好用呢?
欢迎评论留言参与讨论哦~或者加入TheBrain中文交流QQ群( 273298874 ),一起分享你的good idea!
多媒体
2019-07-08 14:24:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
简介
随着客户的增加,mp4文件播放的弊端也日益凸显,主要集中在两个方面
当视频时长比较长的时候,mp4的关键帧元素往往很大,需要加载很长时间才能开始播放,网速不好的情况缓冲加载就要20多秒的时间,客户早已急不可耐。
当用户打开一个视频播放的时候,浏览器会持续请求下载mp4文件直到下载完成,就算是用户暂停视频播放浏览器也会持续这种下载状态,如果这个视频文件是500M则会请求服务器下载500M文件,是1G则会不停下载1G,给服务器硬盘和宽带造成很大浪费和压力。
为了解决上述问题,公司打算使用m3u8格式来替代mp4格式。
m3u8是苹果公司开发的一项新型播放格式,这种播放格式支持目前市面的windows、androis、ios设备主流的浏览器,同样的视频文件既可以在flash环境播放,又能在无flash的html5环境播放,它的优势还不止于此,它可以实现多种码率在不同网速下的自动切换,网速好自动切换高清晰度视频,网速慢自动播放低清晰度文件,还可以实现流加密(视频文件本身加密)、分段下载播放、任意时间点拖拽播放、随机视频文件广告插入等等优势,所以公司打算是用m3u8格式作为视频格式。
mp4转码m3u8
如果视频不为mp4格式,需先将视频转码为mp4,可使用如下命令进行转换 ffmpeg -i 本地视频地址 -y -c:v libx264 -strict -2 转换视频.mp4
将mp4格式转换为ts格式 ffmpeg -y -i 本地视频.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 转换视频.ts
将ts文件进行切片 ffmpeg -i 本地视频.ts -c copy -map 0 -f segment -segment_list 视频索引.m3u8 -segment_time 5 前缀-%03d.ts
其中segment 就是切片,-segment_time表示隔几秒进行切一个文件,上面命令是隔5s,你也可以调整成更大的参数。
转换好的文件
跨域问题
在跨域的网站根目录放 crossdomain.xml 文件,下面是允许所有的网站(一般不采取这样的方式,只是方便调试)均可以跨越访问资源配置如下:
限制指定网站访问,可以参考百度 https://www.baidu.com/crossdomain.xml 配置
如果文件存储在第三方平台上,比如阿里云OSS,就把 crossdomain.xml 放在 bucket 根目录下
播放
这里推荐使用第三方h5播放器 ckplayer ,集成完成后看下视频请求
可以看到视频先加载的 m3u8 格式的索引文件,然后开始加载视频,跟据所以文件依次加载 abc000.ts 、 abc001.ts 、 abc002.ts ,这时候拖动视频,视频开始加载 abc011.ts 、 abc012.ts 、 abc013.ts 跳过了4~10的文件,这就是 m3u8 的好处,按需加载
多媒体
2019-07-04 13:23:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
  
  随着计算机网络技术和物联网的快速发展,在互联网上经常会传输一些敏感数据,比如购物账户、密码等,对于企业来说,网络安全也同样与业务数据安全息息相关。据统计,目前有大约有50%的安全攻击,会通过SSL通道进行,因此传统的很多安全设备将会面临一个很严重的挑战,由此SSL加解密方案的重要性可见一斑。
  如今国内很多的网站、企业已经开始向全站SSL迈进。一些成立时间已经非常长的网站,已经使用了全站SSL。而从行业分布来看,目前国内采用全站SSL加解密的主要还是一些大型电商以及互联网技术使用率高的网站。与其同时,面对无处不在的SSL趋势,只有当互联网上的所有流量都受到加密保护的,才有可能是一个安全的网络环境,那么优秀的SSL加解密解决方案的终极目标就是实现整个流量的加密保护。
 
  SSL加解密方案备受关注
  随着业务的发展,基于性能扩容或功能增强等需求,企业将不断的购买各种各样的安全设备。那么这些新设备如果也需要做SSL解密的话,并不是一件轻松简单的事情。因此我们先来探讨下SSL加解密方案的两个方向,一个是入站方向,另一个则是出站反向,这两个方向所使用的技术以及所解决的用户需求场景是不同的。这里以F5推出的方案为例,了解一下F5在这两个方向上的SSL加解密方案有什么优势之处。
  F5的产品包含了很多的功能模块,提供了很完美的一个安全性的考虑。在F5平台基础上,F5本身作为SSL解密的一个战略控制点,插入了很多的安全模块。F5在入向SSL加解密方面的优势主要在于:提供高性能的运营平台,同时提供了一个可扩展的架构,可以轻松扩展传统硬件设备以及硬件的安全结构。另外一方面,F5提供了一个可扩展的可编程的制度,使得我们可以充分的在数据通道上面去控制数据流量。
  
  F5部署SSL加解密安全解决方案
  整体来看,F5推出的SSL加解密安全解决方案可管理 SSL,为用户提供跨整个安全堆栈的更高性能和效率。同时灵活的部署模式可轻松集成到最复杂的体系结构中,集中处理 SSL 解密和加密,并在用户的整个安全基础架构中提供最新的加密技术。因此,F5的SSL加解密方案是非常值得企业关注的,使业务、数据、流量的安全性都能得到极大的保障。
多媒体
2019-07-03 20:28:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
| 导语 6月29日,北京东直门亚朵S酒店,云+社区邀您参加《音视频及融合通信技术》沙龙活动,深度探讨音视频及融合通信技术的发展及实践,领略前沿,共创价值。

数字多媒体技术的不断发展对音视频及融合通信技术提出了怎样的要求呢?
本期沙龙将邀请腾讯技术专家针对腾讯云音视频及融合通信产品的技术全进行面剖析,围绕最新的低延迟技术、全新的商业直播方案等主题为大家带来纯干货的技术分享,带你走进前沿的音视频及融合通信技术落地实践。

活动信息

活动指南
时间
2019-06-29 周六 13:30-18:00
地点
北京东直门亚朵S酒店(北京市朝阳区香河园路左家庄15号院)
公共交通:
1,乘坐地铁2号线/13号线,东直门地铁站下车,步行约1.2公里
2,乘坐536/131/404/916路等,在左家庄公交站下车,步行约200米

报名渠道
扫描上方二维码 报名

现场奖品
活动现场设置了抽奖环节
大奖将在活动结束后抽出
腾讯定制礼品等你来拿!
一等奖:1名
猫王收音机 MW-R
二等奖:2名
索爱(soaiy)T2 蓝牙耳机无线
三等奖: 3名
罗技(Logitech)K380 键盘
鼓励奖:24名
当当网提供的技术图书

我们还为大家准备了腾讯云公仔
数量有限,先到先得哦!

技术交流
扫描上方二维码添加小助手微信
可提前进群与讲师及参会嘉宾互动交流

直播
如您无法参与现场,
我们也为您准备了线上直播,
直播地址请留意后续的公众号文章,敬请期待~

往期活动





多媒体
2019-06-17 10:09:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
最近工作需要,看了一下小波变换方面的东西,用python实现了一个简单的小波变换类,将来可以用在工作中。

简单说几句原理,小波变换类似于傅里叶变换,都是把函数用一组正交基函数展开,选取不同的基函数给出不同的变换。例如傅里叶变换,选择的是sin和cos,或者exp(ikx)这种复指数函数;而小波变换,选取基函数的方式更加灵活,可以根据要处理的数据的特点(比如某一段上信息量比较多),在不同尺度上采用不同的频宽来对已知信号进行分解,从而尽可能保留多一点信息,同时又避免了原始傅里叶变换的大计算量。以下计算采用的是haar基,它把函数分为2段(A1和B1,但第一次不分),对第一段内相邻的2个采样点进行变换(只考虑A1),变换矩阵为
sqrt(0.5) sqrt(0.5)
sqrt(0.5) -sqrt(0.5)
变换完之后,再把第一段(A1)分为两段,同样对相邻的点进行变换,直到无法再分。

下面直接上代码
Wavelet.py import math class wave: def __init__(self): M_SQRT1_2 = math.sqrt(0.5) self.h1 = [M_SQRT1_2, M_SQRT1_2] self.g1 = [M_SQRT1_2, -M_SQRT1_2] self.h2 = [M_SQRT1_2, M_SQRT1_2] self.g2 = [M_SQRT1_2, -M_SQRT1_2] self.nc = 2 self.offset = 0 def __del__(self): return class Wavelet: def __init__(self, n): self._haar_centered_Init() self._scratch = [] for i in range(0,n): self._scratch.append(0.0) return def __del__(self): return def transform_inverse(self, list, stride): self._wavelet_transform(list, stride, -1) return def transform_forward(self, list, stride): self._wavelet_transform(list, stride, 1) return def _haarInit(self): self._wave = wave() self._wave.offset = 0 return def _haar_centered_Init(self): self._wave = wave() self._wave.offset = 1 return def _wavelet_transform(self, list, stride, dir): n = len(list) if (len(self._scratch) < n): print("not enough workspace provided") exit() if (not self._ispower2(n)): print("the list size is not a power of 2") exit() if (n < 2): return if (dir == 1): # 正变换 i = n while(i >= 2): self._step(list, stride, i, dir) i = i>>1 if (dir == -1): # 逆变换 i = 2 while(i <= n): self._step(list, stride, i, dir) i = i << 1 return def _ispower2(self, n): power = math.log(n,2) intpow = int(power) intn = math.pow(2,intpow) if (abs(n - intn) > 1e-6): return False else: return True def _step(self, list, stride, n, dir): for i in range(0, len(self._scratch)): self._scratch[i] = 0.0 nmod = self._wave.nc * n nmod -= self._wave.offset n1 = n - 1 nh = n >> 1 if (dir == 1): # 正变换 ii = 0 i = 0 while (i < n): h = 0 g = 0 ni = i + nmod for k in range(0, self._wave.nc): jf = n1 & (ni + k) h += self._wave.h1[k] * list[stride*jf] g += self._wave.g1[k] * list[stride*jf] self._scratch[ii] += h self._scratch[ii + nh] += g i += 2 ii += 1 if (dir == -1): # 逆变换 ii = 0 i = 0 while (i < n): ai = list[stride*ii] ai1 = list[stride*(ii+nh)] ni = i + nmod for k in range(0, self._wave.nc): jf = n1 & (ni + k) self._scratch[jf] += self._wave.h2[k] * ai + self._wave.g2[k] * ai1 i += 2 ii += 1 for i in range(0, n): list[stride*i] = self._scratch[i]

测试代码如下:
test.py import math import Wavelet waveletn = 256 waveletnc = 20 #保留的分量数 wavelettest = Wavelet.Wavelet(waveletn) waveletorigindata = [] waveletdata = [] for i in range(0, waveletn): waveletorigindata.append(math.sin(i)*math.exp(-math.pow((i-100)/50,2))+1) waveletdata.append(waveletorigindata[-1]) wavelettest.transform_forward(waveletdata, 1) newdata = sorted(waveletdata, key = lambda ele: abs(ele), reverse=True) for i in range(waveletnc, waveletn): # 筛选出前 waveletnc个分量保留 for j in range(0, waveletn): if (abs(newdata[i] - waveletdata[j]) < 1e-6): waveletdata[j] = 0.0 break wavelettest.transform_inverse(waveletdata, 1) waveleterr = 0.0 for i in range(0, waveletn): print(waveletorigindata[i], ",", waveletdata[i]) waveleterr += abs(waveletorigindata[i] - waveletdata[i])/abs(waveletorigindata[i]) print("error: ", waveleterr/waveletn)

当waveletnc = 20时,可得到下图,误差大约为2.1

当waveletnc = 100时,则为下图,误差大约为0.04

当waveletnc = 200时,得到下图,误差大约为0.0005
多媒体
2019-06-10 19:16:00