• 嵌入式图像上实现软件画线


            在一些嵌入式产品上,经常会遇到要在图像上画线,比如图像上识别出某个物体需要把它框起来,车辆识别需要把识别出来的车框起来,画出框了,看起来就有点味道了,至少说明你真的识别出来了,产品体验上是一个刚需。

         当然单从画线来说,有GUI的产品就太简单了,GUI都有直接的画线接口,这样确实挺简单的。那么在一些没有GUI支持的系统怎么办呢?又不想去借把牛刀来!那么久需要从在图像上直接画出来,也就是改变一下图像上的像素点的值,组成我们需要的线条的表现形式。比较成熟的画线软件算法有布雷森汉姆算法画线,相当经典。如下:

     软件代码实现图像先以YUV420SP来说吧!

      我们知道YUV420SP的图像有两个plane,Y在一个plane上,uv在另外一个plane上,比起uv的plane大小只有Y的一半大小,那么我们在要替换相应像素点的yuv值得时候就可以找到对应的Y和UV的值。DrawPoint的实现如下:

    1. Color = 0
    2. case V4L2_PIX_FMT_NV12:
    3. {
    4. int Yoffset = PntY * ImgW + PntX;
    5. int Uoffset,Voffset;
    6. Uoffset = ImgH * ImgW + (PntY / 2) * ImgW + PntX / 2 * 2 ;
    7. Voffset = Uoffset + 1;
    8. YuvBuf[Yoffset] = s_color_table[Color].Y;
    9. YuvBuf[Uoffset] = s_color_table[Color].U;
    10. YuvBuf[Voffset] = s_color_table[Color].V;
    11. }

    从替换点的yuv值我们可以看出,ImgH,ImgW是图像的宽高, PntY,PntX就是具体像素点位置,要有一个颜色的对应值,支持的颜色多了,我们弄一个颜色对照表,把主要颜色支持上就行了。如下:

    1. static stYuvColor s_color_table[12] =
    2. {
    3. {0x00, 0x00, 0x00}, // green
    4. {0x00, 0x00, 0xff}, // red
    5. {0x00, 0xff, 0x00}, // blue
    6. {0x00, 0xff, 0xff}, // purple
    7. {0xff, 0x00, 0x00}, // dark green
    8. {0xff, 0x00, 0xff}, // yellow
    9. {0xff, 0xff, 0x00}, // light blue
    10. {0xff, 0xff, 0xff}, // light purple
    11. {0x00, 0x80, 0x80}, // dark black
    12. {0x80, 0x80, 0x80}, // gray
    13. {0xff, 0x80, 0x80}, // white
    14. };

    下面就来看看画一条线怎么弄

    1. int YUY_Draw_Line(unsigned char * YuvBuf, int ImgW, int ImgH, int fmt,int SPntX, int SPntY,int EPntX, int EPntY, int Color)
    2. {
    3. int ret = -1;
    4. if(YuvBuf == NULL)
    5. return ret;
    6. // printf("SPntX=%d,EPntX=%d,SPntY=%d,EPntY=%d\n", SPntX, EPntX, SPntY, EPntY);
    7. SPntX = (SPntX + 1>= ImgW) ? (ImgW - 1) : (SPntX < 0 ? 0 : SPntX);
    8. EPntX = (EPntX + 1>= ImgW) ? (ImgW - 1) : (EPntX < 0 ? 0 : EPntX);
    9. SPntY = (SPntY + 1>= ImgH) ? (ImgH - 1) : (SPntY < 0 ? 0 : SPntY);
    10. EPntY = (EPntY + 1>= ImgH) ? (ImgH - 1) : (EPntY < 0 ? 0 : EPntY);
    11. int dx = (SPntX > EPntX) ? (SPntX - EPntX) : (EPntX - SPntX);
    12. int dy = (SPntY > EPntY) ? (SPntY - EPntY) : (EPntY - SPntY);
    13. int xstep = (SPntX < EPntX) ? 1 : -1;
    14. int ystep = (SPntY < EPntY) ? 1 : -1;
    15. int nstep = 0, eps = 0;
    16. int pointX = SPntX;
    17. int pointY = SPntY;
    18. // printf("dx=%d,dy=%d,xstep=%d,ystep=%d,pointX=%d,pointY=%d\n",
    19. // dx, dy, xstep, ystep, pointX, pointY);
    20. if(dx > dy)
    21. {
    22. while(nstep <= dx)
    23. {
    24. ret = YUY_Draw_Piont(YuvBuf, ImgW, ImgH, fmt, pointX, pointY, Color);
    25. if(ret < 0)
    26. break;
    27. eps += dy;
    28. if( (eps << 1) >= dx )
    29. {
    30. pointY += ystep;
    31. eps -= dx;
    32. }
    33. pointX += xstep;
    34. nstep++;
    35. }
    36. }
    37. else
    38. {
    39. while(nstep <= dy)
    40. {
    41. ret = YUY_Draw_Piont(YuvBuf, ImgW, ImgH, fmt, pointX, pointY, Color);
    42. if(ret < 0)
    43. break;
    44. eps += dx;
    45. if( (eps << 1) >= dy )
    46. {
    47. pointX += xstep;
    48. eps -= dy;
    49. }
    50. pointY += ystep;
    51. nstep++;
    52. }
    53. }
    54. return ret;
    55. }

    有了线,我们来画个框吧!也就是4条线围起来,加一点强度,来一个控制线宽的参数:

    1. int YUV_Draw_Rect(unsigned char *YuvBuf, int ImgW, int ImgH, int fmt,RECT* Rect, int Color,int lineWidth)
    2. {
    3. int ret = -1;
    4. int line_width = 1;
    5. if(YuvBuf == NULL)
    6. return ret;
    7. if(Rect->bottom == Rect->top || Rect->left == Rect->right)
    8. return ret;
    9. if(lineWidth > 10)
    10. line_width = 10;//max try 10 pixel
    11. else if(0 == lineWidth)
    12. line_width = 1;//correct to 1
    13. else
    14. line_width = lineWidth;//max try 10 pixel
    15. for(int i=0; i < line_width ; i++){
    16. // top --
    17. YUY_Draw_Line(YuvBuf, ImgW, ImgH,fmt, Rect->left, Rect->top+i , Rect->right, Rect->top+i, Color);
    18. // left |
    19. YUY_Draw_Line(YuvBuf, ImgW, ImgH,fmt, Rect->right-i, Rect->top, Rect->right-i, Rect->bottom, Color);
    20. // right |
    21. YUY_Draw_Line(YuvBuf, ImgW, ImgH,fmt, Rect->left+i, Rect->top , Rect->left+i, Rect->bottom, Color);
    22. // bottom --
    23. YUY_Draw_Line(YuvBuf, ImgW, ImgH,fmt, Rect->left, Rect->bottom-i, Rect->right, Rect->bottom-i, Color);
    24. }
    25. return 0;
    26. }

    里面加了一个线宽最大控制到10个像素,当然也可以根据需要自己调整。看看效果吧!

     

     

    看起来整个效果还是不错的,当然只是展示了一种YUV420SP的图像上画线,其他格式的只要把握好像素点的构成,以及像素点值得分布,来想办法替换掉就行了。思路是一样的。

  • 相关阅读:
    普通用户使用spark的client无法更新Ranger策略
    AtCoder Beginner Contest 277 G(概率dp+计数)
    盘点7种JavaScript常用设计模式
    安卓玩机搞机----不用刷第三方官改固件即可享受“高级设置”的操作 ChiMi安装使用步骤
    Nginx几种负载均衡方式介绍
    建一个chrome插件crx所需步骤
    四化智造MES(WEB)与金蝶云星空对接集成原材料/标准件采购查询(待采购)连通采购订单新增(原材料采购-采购订单(变更)-TEST)
    Spring 框架学习(三)---- IOC创建对象
    处理Activity#onResume()遇到java.lang.IllegalArgumentException诡异异常
    系统架构设计高级技能 · 软件产品线
  • 原文地址:https://blog.csdn.net/sundesheng125/article/details/127578389