设置nv12的矩形边框

论坛 期权论坛 脚本     
匿名网站用户   2020-12-21 09:07   106   0

NV12

一个6*4的nv12格式的图片的三个分量YUV的内存形式:

这里写图片描述

虽然nv12的像素大小是width*height,但是必须为nv12图片分配width*height*3/2的内存空间,因为Y分量所占的内存为width*height,而U,V分量各占width*height/4,见上图即一目了然。

nv12分量YUV分量内存操作:可以用双重for循环遍历nv12各个分量的内存分布,从而实现给nv12图片赋予不同的颜色。

由内存YUV分量内存分布图可以知道:
0 ~ width*height 为Y分量存储的内存范围。
width*height ~ width*height*3/2 为UV交叉存储的内存范围。

操作Y分量:buf[j * width + k]
操作U分量 : buf[j / 2 * width + k - k % 2 + width * height]
操作V分量 : buf[j / 2 * width + k - k % 2 + width * height + 1]

在nv12格式的图片上画一个锁定某个目标的矩形方框图

#include <stdio.h>
#include <stdlib.h>

int nv12_border(char *pic, int pic_w, int pic_h, int rect_x, int rect_y, int rect_w, int rect_h, int R, int G, int B);

int main()
{
    /* Set up the nv12's pixel size */
    const int pic_w  = 1920;
    const int pic_h  = 1080;

    /* Set up test data's path and output data's path */
    char *inputPathname  = "/home/flypei/work/nv12-marked-rect/data/videotestsrc_1920x1080.nv12";
    char *outputPathname = "./outputFile.nv12";

    FILE *fin  = fopen(inputPathname , "rb+");
    FILE *fout = fopen(outputPathname, "wb+");

    /* Allocate memory for nv12 */
    unsigned char *buf = (unsigned char *)malloc(pic_w * pic_h * 3 / 2);

    /* Read file data to buffer */
    fread(buf, 1, pic_w * pic_h * 3 / 2, fin);

    /* Draw rectangle border to nv12 */
    nv12_border(buf, pic_w, pic_h, 500, 500, 300, 400, 0, 0, 255);

    /* Write data of buf to fout */
    fwrite(buf, 1, pic_w * pic_h * 3 / 2, fout);

    /* Free the allocation memory */
    free(buf);

    /* Close the file */
    fclose(fin);
    fclose(fout);

    return 0;
}

int nv12_border(char *pic, int pic_w, int pic_h, int rect_x, int rect_y, int rect_w, int rect_h, int R, int G, int B)
{
    /* Set up the rectangle border size */
    const int border = 5;

    /* RGB convert YUV */
    int Y, U, V;
    Y =  0.299  * R + 0.587  * G + 0.114  * B;
    U = -0.1687 * R + 0.3313 * G + 0.5    * B + 128;
    V =  0.5    * R - 0.4187 * G - 0.0813 * B + 128;

    /* Locking the scope of rectangle border range */
    int j, k;
    for(j = rect_y; j < rect_y + rect_h; j++){
        for(k = rect_x; k < rect_x + rect_w; k++){
            if (k < (rect_x + border) || k > (rect_x + rect_w - border) ||\
                    j < (rect_y + border) || j > (rect_y + rect_h - border)){

                /* Components of YUV's storage address index */
                int y_index = j * pic_w + k;
                int u_index = (y_index / 2 - pic_w / 2 * ((j + 1) / 2)) * 2 + pic_w * pic_h;
                int v_index = u_index + 1;

                /* set up YUV's conponents value of rectangle border */
                pic[y_index] =  Y ;
                pic[u_index] =  U ;
                pic[v_index] =  V ;
            }
        }
    }

    return 0;
}

原nv12图片(用yuvplayer查看):
这里写图片描述
加上方框的nv12图片(用yuvplayer查看):
这里写图片描述


demo优化版

#include <stdio.h>
#include <stdlib.h>

#define uchar unsigned char

typedef struct rectangle{
    int x;
    int y;
    int w;
    int h;
    uchar thin;
    uchar YUV[3];
}RECT;

void RgbToYuv(uchar RGB[], uchar YUV[]);
void FindAxis(RECT rect[], int n, int rect_all_axis[]);
void DrawWidthLine(uchar* pic, int pic_w, int pic_h, RECT rect[], int n, int axis[]);
void DrawHeightLine(uchar* pic, int pic_w, int pic_h, RECT rect[], int n, int axis[]);
void DrawPoint(uchar* pic, int pic_w, int pic_h, int point_axis[], int count, uchar YUV[]);
void NV12MarkRect(uchar* pic, int pic_w, int pic_h, RECT rect[], int n, int point_axis[], int count);

int main()
{
    /*****************************************************/
    /****                                             ****/
    /****             Configure Parameter             ****/
    /****                                             ****/
    /*****************************************************/

    /* Config the nv12's pixel size */
    const int pict_w  = 1920;
    const int pict_h  = 1080;
    int picSize = pict_w * pict_h * 1.5;

    /* Allocate memory for nv12 */
    uchar* picBuf = (unsigned char *)malloc(picSize);

    /* RGB convert to YUV */
    uchar RGBblue[3] = {255, 0, 0};
    uchar YUVblue[3];
    RgbToYuv(RGBblue, YUVblue);

    /* Config rectangle's quanlity and parameter */
    int n = 2;
    uchar t = 1;
    RECT Rect[] = {
        {
            .x = 0,
            .y = 0,
            .w = 96,
            .h = 96,
            .thin = t,
            .YUV[0] = YUVblue[0],
            .YUV[1] = YUVblue[1],
            .YUV[2] = YUVblue[2] },
        {
            .x = 144,
            .y = 144,
            .w = 128,
            .h = 128,
            .thin = t,
            .YUV[0] = YUVblue[0],
            .YUV[1] = YUVblue[1],
            .YUV[2] = YUVblue[2] }
    };

    /* Config point axis's count and draw the point at NV12 */
    int c = 30;
    int point[] = { 12,233, 132,15, 142,22, 312,34, 112,45, 212,58, 127,62, 132,72, 212,84, 129,91,
                    112,66, 187,38, 155,13, 145,56, 134,23, 165,56, 176,67, 189,87, 174,52, 121,99,
                    212,66, 287,38, 255,13, 245,56, 234,23, 265,56, 276,67, 289,87, 274,52, 221,99 };

    /* Config input and output path */
    char input[255]  = "videotestsrc_1920x1080.nv12";
    char output[255] = "outputFile.nv12";

    /******************************************************/

    FILE *fin  = fopen(input,  "rb");
    FILE *fout = fopen(output, "wb+");

    /* Read file data to buffer */
    fread(picBuf, 1, picSize, fin);

    /* Draw rectangle and point to nv12 */
    NV12MarkRect(picBuf, pict_w, pict_h, Rect, n, point, c);

    /* Write data of buf to fout */
    fwrite(picBuf, 1, picSize, fout);

    /* Free the allocation memory */
    free(picBuf);

    /* Close the file */
    fclose(fin);
    fclose(fout);

    return 0;
}

void RgbToYuv(uchar RGB[3], uchar YUV[3])
{
    /* RGB convert YUV */
    YUV[0] =  0.299  * RGB[0] + 0.587  * RGB[1] + 0.114  * RGB[2];
    YUV[1] = -0.1687 * RGB[0] + 0.3313 * RGB[1] + 0.5    * RGB[2] + 128;
    YUV[2] =  0.5    * RGB[0] - 0.4187 * RGB[1] - 0.0813 * RGB[2] + 128;
}

void FindAxis(RECT rect[], int n, int axis[])
{
    axis[0] = axis[2] = axis[4] = rect[n].x;
    axis[6] = rect[n].x + rect[n].w - rect[n].thin;
    axis[1] = rect[n].y;
    axis[3] = rect[n].y + rect[n].h - rect[n].thin;
    axis[5] = axis[7] = rect[n].y + rect[n].thin;
}

void DrawWidthLine(uchar* pic, int pic_w, int pic_h, RECT rect[], int n, int axis[])
{
    int i, j, k;
    int y_index, u_index, v_index;
    for (i = 0; i < 4; i += 2){
        for (j = axis[i+1]+rect[n].thin-1; j >= axis[i+1]; j--){
            for (k = axis[i]+rect[n].w-1; k >= axis[i]; k--){

                y_index = j * pic_w + k;
                u_index = ((j >> 1) + pic_h) * pic_w + k - (k & 1);
                //u_index = (((y_index >> 1) - (pic_w >> 1) * ((j + 1) >> 1)) << 1) + pic_w * pic_h;
                v_index = u_index + 1;

                pic[y_index] = rect[n].YUV[0];
                pic[u_index] = rect[n].YUV[1];
                pic[v_index] = rect[n].YUV[2];

            }
        }
    }
}

void DrawHeightLine(uchar* pic, int pic_w, int pic_h, RECT rect[], int n, int axis[])
{
    int i, j, k;
    int y_index, u_index, v_index;
    for (i = 4; i < 8; i += 2){
        for (k = axis[i]+rect[n].thin-1; k >= axis[i]; k--){
            for (j = axis[i+1]+rect[n].h-(2*rect[n].thin)-1; j >= axis[i+1]; j--){
                y_index = j * pic_w + k;
                u_index = ((j >> 1) + pic_h) * pic_w + k - (k & 1);
                //u_index = (((y_index >> 1) - (pic_w >> 1) * ((j + 1) >> 1)) << 1) + pic_w * pic_h;
                v_index = u_index + 1;

                pic[y_index] = rect[n].YUV[0];
                pic[u_index] = rect[n].YUV[1];
                pic[v_index] = rect[n].YUV[2];

            }
        }
    }
}

void DrawPoint(uchar* pic, int pic_w, int pic_h, int point_axis[], int count, uchar YUV[])
{
    /* Draw points at NV12 */
    int a, y_point, u_point, v_point;
    for (a = (count-1)*2; a >= 0; a -= 2){

            y_point = point_axis[a+1] * pic_w + point_axis[a];
            u_point = ((point_axis[a+1] >> 1) + pic_h) * pic_w + point_axis[a] - (point_axis[a] & 1);
            //u_point = (((y_point >> 1) - (pic_w >> 1) * ((point_axis[a+1] + 1) >> 1)) << 1) + pic_w * pic_h;
            v_point = u_point + 1;

            pic[y_point] = YUV[0];
            pic[u_point] = YUV[1];
            pic[v_point] = YUV[2];
    }

}

void NV12MarkRect(uchar* pic, int pic_w, int pic_h, RECT rect[], int num, int point_axis[], int count)
{
    int i;
    int axis[8];

    for (i = num-1; i >= 0; i--){

        FindAxis(rect, i, axis);
        DrawWidthLine(pic, pic_w, pic_h, rect, i, axis);
        DrawHeightLine(pic, pic_w, pic_h, rect, i, axis);
    }

    DrawPoint(pic, pic_w, pic_h, point_axis, count, rect[0].YUV);
}
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP