美文网首页
几种简单的图像数据处理操作

几种简单的图像数据处理操作

作者: 窝窝蜗牛 | 来源:发表于2020-11-09 09:53 被阅读0次

    前言

    图像数据处理由于处理繁琐,数据量大,为了不占用cpu资源,一般由硬件模块处理,或者由GPU做处理。但是,对于一些简单的处理操作,我们还是有必要学习一下,因为有些简单场景没有必要调用硬件资源。以下操作虽然简单,但是我也调试了千万遍,才知道“纸上得来终觉浅,绝知此事要躬行”。

    一、RGB的flip操作

    LOCAL void _rgb_flip(uint16 *addr,int width,int height)
    {   
        uint8 i = 0, j = 0;
        uint16 tmp_data = 0;
        for(i = 0;i < height;i++)
        {
            for(j = 0;j < width / 2;j++)
            {
                tmp_data = *(addr + j);
                *(addr + j) = *(addr + width - j - 1);
                *(addr + width - j - 1) = tmp_data;
            }
            addr += width;
        }   
    }
    

    rgb的存储格式是一个像素点对应一个数据存储,例如,RGB565的存储格式如下,所以一个像素点占俩字节,该算法也只适用565格式,不适用888格式


    rgb565存储格式

    二、YUV的填充操作

    void _ISP_YUV420pFillBlack(ISP_ADDRESS_T *src, ISP_ADDRESS_T *dst,
                                           uint32 src_w, uint32 src_h,     uint32 dst_w, uint32 dst_h)
    {
           uint32 s_y = src->yaddr, s_u = src->uaddr;
           uint32 d_y = dst->yaddr, d_u = dst->uaddr;
           uint8 y_value = 0, u_value = 128; //black
           if (dst_w > src_w && dst_h == src_h && (dst_w - src_w) % 4 == 0) {
                   ISPSRV_LOGI("Fill in width");
                   uint32 offset = (dst_w - src_w) >> 1;
                   uint32 offset_ = dst_w - src_w - offset;
                   for (int i = 0; i < dst_h; i++){
                           SCI_MEMSET((void *)d_y, y_value, offset);
                           d_y += offset;
                           SCI_MEMCPY((void *)d_y, s_y, src_w);
                           d_y += src_w, s_y += src_w;
                           SCI_MEMSET((void *)d_y, y_value, offset_);
                           d_y += offset_;
    
                           SCI_MEMSET((void *)d_u, u_value, offset >> 1);
                           d_u +=  offset >> 1;
                           SCI_MEMCPY((void *)d_u, s_u, src_w>>1);
                           d_u += src_w>>1, s_u += src_w>>1;
                           SCI_MEMSET((void *)d_u, u_value, offset_ >> 1);
                           d_u += offset_ >> 1;
                   }
           } else if (dst_w == src_w && dst_h > src_h && (dst_h - src_h) % 4 == 0) {
                   ISPSRV_LOGI("Fill in height");
                   uint32 offset = (dst_h - src_h)>>1;
                   uint32 offset_ = dst_h - src_h - offset;
                   SCI_MEMSET((void *)d_y, y_value, offset * dst_w);
                   d_y += offset * dst_w;
                   SCI_MEMCPY((void *)d_y, s_y, src_w * src_h);
                   d_y += dst_w * src_h;
                   SCI_MEMSET((void *)d_y, y_value, offset_ * dst_w);
                   d_y += offset_ * dst_w;
    
                   SCI_MEMSET((void *)d_u, u_value, (offset * src_w) >>1);
                   d_u += (offset * src_w) >>1;
                   SCI_MEMCPY((void *)d_u, s_u, (src_w * src_h) >> 1);
                   d_u += (src_w * src_h) >> 1;
                   SCI_MEMSET((void *)d_u, u_value, (offset_ * src_w)>>1);
                   d_u += (offset_ * src_w)>>1;
           } else {
                   ISPSRV_LOGE("Size error !!!");
           }
    }
    

    该填充操作上半部分是未经过验证的,应该还存在问题,贴上去只为了凑点字数,看Fill in height即可
    三、YUV的裁剪操作

    void _ISP_YUV420pCutBlack(ISP_ADDRESS_T *src, ISP_ADDRESS_T *dst,
                                           uint32 src_w, uint32 src_h,     uint32 dst_w, uint32 dst_h)
    {
           uint32 s_y = src->yaddr, s_u = src->uaddr;
           uint32 d_y = dst->yaddr, d_u = dst->uaddr;
           uint8 y_value = 0,u_value = 128;
           uint32 width = 0,height = 0;
    
           ISPSRV_LOGI("cut in width");
           uint32 offset = (src_w - dst_w)>>1;
           uint32 offset_ = src_w - dst_w - offset;
           s_y += offset;
           for(height = 0;height < dst_h;height++)
           {
                SCI_MEMCPY(d_y,s_y,dst_w);
                d_y += dst_w;
                s_y += src_w;
           }
    
           s_u += offset;
           for(height = 0;height < (dst_h >> 1);height++)
           {
                SCI_MEMCPY(d_u,s_u,dst_w);
                d_u += dst_w;
                s_u += src_w;
           }
    }
    

    针对YUV的填充和裁剪,最重要的就是要搞清楚YUV的数据存储格式,以上算法也是针对YUV420格式的


    yuv420存储格式

    之前参考别人代码,纳闷为什么只对y和u地址操作,而不做v地址操作,仔细一看会发现做u地址处理时已经把v数据也处理了。

    相关文章

      网友评论

          本文标题:几种简单的图像数据处理操作

          本文链接:https://www.haomeiwen.com/subject/xtxlbktx.html