zoukankan      html  css  js  c++  java
  • YUV420图像旋转90算法的优化

            在做android摄像头捕获时,发现从android摄像头出来的原始视是逆时针旋转了90度的,所以须要把它顺时针旋转90。android视频支持的是NV21格式,它是一种YUV420的格式。当然,始果你用的是android sdk的话,当中image就提供这个能力。可是我是在ndk下开发,没有找到对应的功能(假设你知道请告诉我)。

             我本想用开源的图像处理库(opencv)做旋转,可是opencv仅仅能处理bmp的图像。这种话,须要先把NV21转换成BMP32。然后再做旋转。所以要操作两次,效率肯定低。最后也没找到好的方法(假设你知道一次用opencv做YUV420格式的旋转,请你告诉我)。所以仅仅有自己写一个。

    先从网上搜索了一个:

    void CTool::YUV420spRotate90(uchar *des, uchar *src,int width,int height)
    {
        int wh = width * height;
        //旋转Y
        int k = 0;
        for(int i = 0; i < width; i++) {
            for(int j = 0; j < height; j++)
            {
                des[k] = src[width * j + i];
                k++;
            }
        }
    
        for(int i = 0; i < width; i += 2) {
            for(int j = 0; j < height / 2; j++)
            {
                des[k] = src[wh+ width * j + i];
                des[k+1] = src[wh + width * j + i + 1];
                k+=2;
            }
        }
    }
    

    在android上执行了一下,发现视频很卡。所以仅仅有自己优化了。这段代码里有乘法,优化的重点就是去掉乘法用加法取代:

    void CTool::YUV420spRotate90(uchar *dst, const uchar *src, int srcWidth, int srcHeight)
    {
        static int nWidth = 0, nHeight = 0;
        static int wh = 0;
        static int uvHeight = 0;
        if(srcWidth != nWidth || srcHeight != nHeight)
        {
            nWidth = srcWidth;
            nHeight = srcHeight;
            wh = srcWidth * srcHeight;
            uvHeight = srcHeight >> 1;//uvHeight = height / 2
        }
    
        //旋转Y
        int k = 0;
        for(int i = 0; i < srcWidth; i++) {
            int nPos = 0;
            for(int j = 0; j < srcHeight; j++) {
                dst[k] = src[nPos + i];
                k++;
                nPos += srcWidth;
            }
        }
    
        for(int i = 0; i < srcWidth; i+=2){
            int nPos = wh;
            for(int j = 0; j < uvHeight; j++) {
                dst[k] = src[nPos + i];
                dst[k + 1] = src[nPos + i + 1];
                k += 2;
                nPos += srcWidth;
            }
        }
        return;
    }


    逆时针旋转90度:

    void CTool::YUV420spRotateNegative90(uchar *dst, const uchar *src, int srcWidth, int height)
    {
        static int nWidth = 0, nHeight = 0;
        static int wh = 0;
        static int uvHeight = 0;
        if(srcWidth != nWidth || height != nHeight)
        {
            nWidth = srcWidth;
            nHeight = height;
            wh = srcWidth * height;
            uvHeight = height >> 1;//uvHeight = height / 2
        }
    
        //旋转Y
        int k = 0;
        for(int i = 0; i < srcWidth; i++){
            int nPos = srcWidth - 1;
            for(int j = 0; j < height; j++)
            {
                dst[k] = src[nPos - i];
                k++;
                nPos += srcWidth;
            }
        }
    
        for(int i = 0; i < srcWidth; i+=2){
            int nPos = wh + srcWidth - 1;
            for(int j = 0; j < uvHeight; j++) {
                dst[k] = src[nPos - i - 1];
                dst[k + 1] = src[nPos - i];
                k += 2;
                nPos += srcWidth;
            }
        }
    
        return;
    }
    


     编译执行,捕获视频显示很流畅 :)

  • 相关阅读:
    前端通过Nginx反向代理解决跨域问题
    SpringMVC解决跨域问题
    SpringMVC空字符串转为null
    什么是优秀的程序员
    Windows下Nginx实现负载均衡
    SpringMVC实现PUT请求上传文件
    设计模式解密(6)
    设计模式解密(5)- 外观模式(门面模式)
    设计模式解密(4)- 模板方法模式
    eclipse上传新项目到GitHub
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3746231.html
Copyright © 2011-2022 走看看