1)基于C语言软件实现某一张YUV420图像特定区域打马赛克,分享给将要学习或者正在学习图像开发的同学。后面贴完整源码。
2)适用于对C语言有基本的认识,以及对Linux驱动知识有基本的掌握能力。
4)内容属于原创,若转载,请说明出处。
5)提供相关问题有偿答疑和支持。
下面是具体实现:
1)取一张YUV420的图像NV12的格式
2)将上图的人脸打马赛克
3)主要实现的code
定义马赛克的位置以及大小,和打码的宏块数目:
#define YUV420_WIDTH 1920
#define YUV420_HIGH 1080
#define YUV420_SIZE (YUV420_WIDTH * YUV420_HIGH * 3/2)
#define MOSAIC_WIDTH 500
#define MOSAIC_HIGH 500
#define MOSAIC_X 750
#define MOSAIC_Y 150
#define MOSAIC_DIV 20 //25x25
#define MOSAIC_XN (MOSAIC_WIDTH/MOSAIC_DIV)
#define MOSAIC_YN (MOSAIC_HIGH/MOSAIC_DIV)
#define MOSAIC_SIZE (MOSAIC_WIDTH * MOSAIC_HIGH * 3/2)
对原始的YUV进行crop:
int yuv_crop(char *nv12data, int width, int height, int cropx,
int cropy, char *yuv420pdata, int dscw, int dsch)
{
char *ptry = yuv420pdata, *ptru, *ptrv;
char *nvptr = nv12data + width * height;
ptry = yuv420pdata;
ptru = yuv420pdata + dscw * dsch;
ptrv = yuv420pdata + dscw * dsch + 1;
// copy y
for (int y = cropy; y < dsch + cropy; y++)
{
memcpy(ptry, nv12data + y * width + cropx, dscw);
ptry += dscw;
}
// copy uv
for (int nvy = cropy / 2; nvy < dsch / 2 + cropy / 2; nvy++)
{
for (int nvx = cropx; nvx < dscw + cropx; nvx++)
{
if (nvx % 2 == 0)
{
*ptru = nvptr[nvy * width + nvx];
ptru+=2;
}
else
{
*ptrv= nvptr[nvy * width + nvx];
ptrv+=2;
}
}
}
return 0;
}
对单个宏块进行填充:主要是取每一个小宏块的左上角的一个像素填充整个小宏块
void fill_pixels(unsigned char *bmp_data, int h, int w, unsigned short font_data)
{
unsigned short *pixel = (unsigned short *)bmp_data;
int pos = (h * MOSAIC_DIV * MOSAIC_WIDTH) + (w * MOSAIC_DIV);
//printf("pos: %d, %d\n", pos, font_data);
for(int i=0; i<MOSAIC_DIV; i++)
{
for(int j=0; j<MOSAIC_DIV; j++)
{
pixel[pos + j] = font_data;
}
pos += MOSAIC_WIDTH;
}
}
完整代码: