51Halcon机器视觉

 找回密码
 会员注册

QQ登录

只需一步,快速开始

扫一扫,微信登录

查看: 407|回复: 1

[资料] C#与Halcon学习——Bitmap转换为HObject

[复制链接]
  • TA的每日心情
    可怜
    半小时前
  • 签到天数: 91 天

    连续签到: 11 天

    [LV.6]常住居民II

    4

    主题

    46

    帖子

    249

    积分

    Rank: 2Rank: 2

    积分
    249
    发表于 2020-6-18 15:16:50 | 显示全部楼层 |阅读模式

    51Halcon诚邀您的加入,专注于机器视觉开发与应用技术,我们一直都在努力!

    您需要 登录 才可以下载或查看,没有帐号?会员注册

    x
    前两天掉进一个大坑,记录一下。写接口的时候要求输入为Image或Bitmap的数据类型,所以在用Halcon处理之前要先把它们编程Hobject的数据类型,在网上搜了一下相关的转换方法,大多是先利用了BitmapData中的LockBits和UnLockBits,取出位图的存储首地址,然后再利用Halcon里的GenImage系列函数根据位图地址创建一个新的HObject。根据这种方法我对图像类型进行了转换,然后就发现原来的算法不起作用了,将转换后的图像用Halcon打开,发现变成了如下这样。

    原图

    原图

    图像扭曲

    图像扭曲

    整个图就已经扭曲了。。

    产生这种结果的代码如下:

    public void Bitmap2HObjectBpp8(Bitmap SrcImage, out HObject image)
            {
                try
                {
                    Point po = new Point(0, 0);
                    Size so = new Size(SrcImage.Width, SrcImage.Height);//template.Width, template.Height
                    Rectangle ro = new Rectangle(po, so);

                    Bitmap DstImg = new Bitmap(SrcImage.Width, SrcImage.Height, PixelFormat.Format8bppIndexed);
                    DstImg = SrcImage.Clone(ro, PixelFormat.Format8bppIndexed);

                    Rectangle rect = new Rectangle(0, 0, DstImg.Width, DstImg.Height);
                    BitmapData srcBmpData = DstImg.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
                    HOperatorSet.GenImage1(out image, "byte", DstImg.Width, DstImg.Height, srcBmpData.Scan0);
                    DstImg.UnlockBits(srcBmpData);

                }
                catch (Exception ex)
                {
                    image = null;
                }
            }
    最开始以为是图像的位数导致的,然后就把所有的图像转为Format8bppIndexed型,还是存在这个问题,就又仔细去看了GenImage1的文档,里面有一句话是Care must be taken not to truncate 64-bit pointers on 64-bit architectures,以为是指针有问题,弄了半天也搞懂为什么。然后偶然间发现这个转换方法对某些图是起作用的,然后看了图的尺寸为4032*3024(在此感谢上苍感谢我的手机。。),发现4032是64的倍数,此刻便开始怀疑这种方法的遍历是不是并非想象中的那样。

    于是把目标转移到Scan0上,确实它是位图的首地址,而GenImage1里提到The pixels in PixelPointer are stored line-sequentially,在我们的结果中可以看到一条明显的分割线。

    明显有条线

    明显有条线



    因此猜测是扫描的问题,去数了一下图中黑线在每一行的像素。。发现是delta=64*n-width,其中delta的取值范围是0~3,在此基本就真相大白了,去查了一下BitmapData类,发现其中的有一个属性是Stride,也就是扫描一行的字节数,它是4的倍数,所以说如果按照这个顺序来赋值内存的话,对于宽度不是64倍数的图片来说,不仅会丢失信息,还会造成图片的扭曲,并产生一个黑线。所以在使用GenImage系列的函数时,我们不能直接用Bitmap里面的Scan0指针。

    对相关代码进行修改:

    public static HObject BitmapToHImage(Bitmap SrcImage)
            {
                HObject Hobj;
                HOperatorSet.GenEmptyObj(out Hobj);

                Point po = new Point(0, 0);
                Size so = new Size(SrcImage.Width, SrcImage.Height);//template.Width, template.Height
                Rectangle ro = new Rectangle(po, so);

                Bitmap DstImage = new Bitmap(SrcImage.Width, SrcImage.Height, PixelFormat.Format8bppIndexed);
                DstImage = SrcImage.Clone(ro, PixelFormat.Format8bppIndexed);

                int width = DstImage.Width;
                int height = DstImage.Height;

                Rectangle rect = new Rectangle(0, 0, width, height);
                System.Drawing.Imaging.BitmapData dstBmpData =
                    DstImage.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);//pImage.PixelFormat
                int PixelSize = Bitmap.GetPixelFormatSize(dstBmpData.PixelFormat) / 8;
                int stride = dstBmpData.Stride;

                //重点在此
                unsafe
                {
                    int count = height * width;
                    byte[] data = new byte[count];
                    byte* bptr = (byte*)dstBmpData.Scan0;
                    fixed (byte* pData = data)
                    {
                        for (int i = 0; i < height; i++)
                            for (int j = 0; j < width; j++ )
                                {
                                     data[i * width + j ] = bptr[i * stride + j];
                                }
                        HOperatorSet.GenImage1(out Hobj, "byte", width, height, new IntPtr(pData));
                    }
                }

                DstImage.UnlockBits(dstBmpData);

                return Hobj;
            }
    修改之后,就可以发现转换的结果没有问题啦!同样的方法也可以用在转换24位彩色图像上,只要记得这个Stride就行了。。
    3.png
    4.png

    C#与Halcon学习——Bitmap转换为HObject.pdf

    1.02 MB, 下载次数: 14, 下载积分: 金币 -2

    1.发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

    2.提问请组织好自己的逻辑,标题注明大概是什么问题,问题内容写详细,需提供问题症状、错误代码、截图、位置等等信息,不要让别人去猜你想问啥;

    3.如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题前面加上【已解决】

    4.回报帮助你解决问题的坛友,右下角【免费评分】赠与对方视觉币和热心值,伸手党遭人唾弃,做一个热心并受欢迎的人!

  • TA的每日心情
    振奋
    1 小时前
  • 签到天数: 285 天

    连续签到: 2 天

    [LV.8]以坛为家I

    0

    主题

    27

    帖子

    610

    积分

    Rank: 3

    积分
    610
    发表于 2020-6-20 08:06:55 | 显示全部楼层
    可以的。。。。。。。。。。

    1.发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

    2.提问请组织好自己的逻辑,标题注明大概是什么问题,问题内容写详细,需提供问题症状、错误代码、截图、位置等等信息,不要让别人去猜你想问啥;

    3.如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题前面加上【已解决】

    4.回报帮助你解决问题的坛友,右下角【免费评分】赠与对方视觉币和热心值,伸手党遭人唾弃,做一个热心并受欢迎的人!

    您需要登录后才可以回帖 会员登录 | 会员注册

    本版积分规则

    建议您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流浏览器浏览本网站

    51Halcon会员技术交流会员技术交流 | 51Halcon官方客服咨询官方客服咨询 | Halcon切换助手使用反馈切换助手使用

    有问题需要咨询站长?| 申请友链| 小黑屋| 手机版| Archiver|  

    粤ICP备15095995号-2 粤公网安备44030602000670号

    CopyRight © 2015-2020 51Halcon机器视觉. Tencent Cloud X3.4.

    快速回复 返回顶部 返回列表