NV21裁剪 縮放

2021-10-01 02:28:43 字數 2652 閱讀 8380

nv21裁剪演算法

最近,在做android攝像頭預覽方法的事情,usb攝像頭出來的資料都是16:9的,無法正常在豎屏狀態下顯示,所以就要對攝像頭的資料進行裁剪處理,攝像頭出來的資料是nv21(就是yuv420sp)格式,libyuv的裁剪演算法是針對i420格式進行操作,裁剪nv21就得進行格式轉換,乙個裁剪需要三個操作,效率可想而知,經過測試libyuv對1920x1080進行裁剪,在rk3399上需要耗時40ms左右,算了,自己研究了一下,寫了乙個裁剪演算法,水平差,寫了個的nv21裁剪演算法,首先是要了解 nv21的資料格式,網上太多文章了,我就不贅述了

nv21格式 yyyyyyyyvuvu

好了,開始裁剪吧,裁剪就是刪資料嘛

/*** nv21裁剪 by lake 演算法效率 11ms

** @param src    源資料

* @param width  源寬

* @param height 源高

* @param left   頂點座標

* @param top    頂點座標

* @param clip_w 裁剪後的寬

* @param clip_h 裁剪後的高

* @return 裁剪後的資料

*/public static byte cropnv21(byte src, int width, int height, int left, int top, int clip_w, int clip_h)

//取偶

int x = left / 2 * 2 , y = top / 2 * 2 ;

int w = clip_w / 2 * 2 , h = clip_h / 2 * 2 ;

int y_unit = w * h;

int src_unit = width * height;

int uv = y_unit >> 1;

byte ndata = new byte[y_unit + uv];

for (int i = y, len_i = y + h; i < len_i; i++)

}return ndata;

}原理很簡單,就是源資料根據條件把yvu塞到乙個新陣列裡,測試一下這個演算法,需要11ms,還是太慢了。參照了一下別人c實現的裁剪演算法。做了一下修改

/*** nv21裁剪  演算法效率 3ms

** @param src    源資料

* @param width  源寬

* @param height 源高

* @param left   頂點座標

* @param top    頂點座標

* @param clip_w 裁剪後的寬

* @param clip_h 裁剪後的高

* @return 裁剪後的資料

*/public static byte clipnv21(byte src, int width, int height, int left, int top, int clip_w, int clip_h)

//取偶

int x = left / 2 * 2, y = top / 2 * 2;

int w = clip_w / 2 * 2, h = clip_h / 2 * 2;

int y_unit = w * h;

int uv = y_unit / 2;

byte ndata = new byte[y_unit + uv];

int uv_index_dst = w * h - y / 2 * w;

int uv_index_src = width * height + x;

int srcpos0 = y * width;

int destpos0 = 0;

int uvsrcpos0 = uv_index_src;

int uvdestpos0 = uv_index_dst;

for (int i = y; i < y + h; i++)

}return ndata;

}執行一下,只需要2ms~3ms就能裁剪完。

接著自己又實現了一下nv21裁剪的同時進行映象操作。

/*** 剪下nv21資料並且映象 演算法效率1080x1920 14ms 1280x720 6ms

** @param src

* @param width

* @param height

* @param left

* @param top

* @param clip_w

* @param clip_h

* @return

*/public static byte clipmirrornv21(byte src, int width, int height, int left, int top, int clip_w, int clip_h)

//取偶

int x = left, y = top;

int w = clip_w, h = clip_h;

int y_unit = w * h;

int src_unit = width * height;

int uv = y_unit / 2;

byte ndata = new byte[y_unit + uv];

int npos = (y - 1) * width;

int mpos;

nv21 yuv420sp 水平映象翻轉實現

輸入資料是yuv,輸出是flipyuv,uv分量是交替儲存,uvsize剛好是height 2 width,下面的實現沒有考慮stride的情況。void cvtnv21fliph mat myuv,mat mflipyuv flip vu data int ylen width height fo...