Halcon 高效的Hobject格式转换Bitmap24位方式

Halcon 高效的Hobject格式转换Bitmap24位方式

近期需要halcon图片格式Hobject到windows图片格式Bitmap 24位的转换,在网上搜寻多时,没有发现合适的。普遍的做法是Hobject格式转为Bitmap32位,然后再从Bitmap32位转为24位,这种做法虽然能达到目的,但是对于有时间要求的算法来说,显然不是最优解。因此本文提出一种基于halcon库的转换方式,从rgb模式的Hobject直转Bitmap24位,同时兼顾耗时要求。
要点:
1.Halcon图像格式与Bitmap格式的不同,如下图所示,左侧为halcon的中RGB三通道图的各个通道排布,右侧为Bitmap的RGB排布,可以看出Bitmap中使用的是交错图像格式。Hobject向Bitmap转换的关键即从独立排布生成交错排布。图片源:HALCON: Bitmap HImage Conversion
Halcon 高效的Hobject格式转换Bitmap24位方式_第1张图片
2.Bitmap的存储方式要求每行的字节数必须能被4整除,因此不满足的需要进行padding。这个特性决定了转换时转成32位即Format32bppRgb格式是最方便的,单通道位图和三通道位图可以转换为32位/像素格式,这意味着位图的每一行可以直接被4整除,而不需要padding。但是有的时候并不需要32位的bitmap,而是24的。

方法1:

网上容易搜得到的,针对不同尺寸图像均适用的Hobejct转24位Bitmap的方式:Hobject——>Bitmap32——>Bitmap24。
代码如下:
Hobject转32为Bitmap,代码参考:《Halcon HObject和C# Bitmap图像互转的几种方式及转换时间测试》
此文中虽然写的是转24位,但是代码实际还是转32位。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using HalconDotNet;
using System.Drawing.Imaging;
/// 
		[DllImport("kernel32.dll")]
        public static extern void CopyMemory(int Destination, int add, int Length);
        System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
        System.Diagnostics.Stopwatch watch2 = new System.Diagnostics.Stopwatch();
        /// HObject转32位Bitmap(四通道)
        /// 
        /// 
        /// 
        private void HObject2Bpp32(HObject image, out Bitmap res)
        {
            try
            {
                HTuple hred, hgreen, hblue, type, width, height;
 
                HOperatorSet.GetImagePointer3(image, out hred, out hgreen, out hblue, out type, out width, out height);
 
                res = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
 
                Rectangle rect = new Rectangle(0, 0, width, height);
                BitmapData bitmapData = res.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
                int imglength = width * height;
                unsafe
                {
                    byte* bptr = (byte*)bitmapData.Scan0;
                    byte* r = ((byte*)hred.I);
                    byte* g = ((byte*)hgreen.I);
                    byte* b = ((byte*)hblue.I);
                    for (int i = 0; i < imglength; i++)
                    {
                        bptr[i * 4] = (b)[i];
                        bptr[i * 4 + 1] = (g)[i];
                        bptr[i * 4 + 2] = (r)[i];
                        bptr[i * 4 + 3] = 255;
                    }
                }
 
                res.UnlockBits(bitmapData);
            }
            catch(Exception ex)
            {
                res = null;
                throw ex;
            }
        }

Bitmap 32转Bitmap 24,构造新的Bitmap对象然后进行重绘操作得到24位Bitmap

Bitmap _tobmpImage;
//Hobject转32位Bitmap
HObject2Bpp32(ho_image, out _tobmpImage);
//32位Bitmap转24位
res24 = new Bitmap(_tobmpImage.Width, _tobmpImage.Height, PixelFormat.Format24bppRgb);
Graphics graphics = Graphics.FromImage(res24);
graphics.DrawImage(_tobmpImage, new Rectangle(0, 0, _tobmpImage.Width, _tobmpImage.Height));

方法2:

主要利用halcon中inter_leave_channels()算子来创建符合bitmap的交错图片格式,此算子的参数可以参看halcon的帮助文档,关键为rowBytes参数值选择,默认为“match”,即默认图片不需要padding,若图片尺寸不满足直接转为24位的条件,需要使用padding时,则其值设定为4倍的图像宽度。具体代码如下:

//获取图像尺寸
HOperatorSet.GetImageSize(ho_image, out width0, out height0);
//创建交错格式图像
HOperatorSet.InterleaveChannels(ho_image, out HObject InterImage, "rgb", 4 * width0, 0);
//获取交错格式图像指针
HOperatorSet.GetImagePointer1(InterImage, out HTuple Pointer, out type, out width, out height);
IntPtr ptr = Pointer;
//构建新Bitmap图像
res24 = new Bitmap(width/4, height, width, PixelFormat.Format24bppRgb, ptr);

通过测试,方法2在转换速度上约为方法1的3~4倍(具体速度提升数值取决于硬件性能),同时能满足不同尺寸的RGB彩图转换。在笔者电脑实测4096×3000的1200万像素彩图,方法2耗时35ms,方法1耗时115ms,图像尺寸越大,速度差异对比越发明显。因此方法2适合在算法耗时要求较为严格的情况下使用,代码更加简洁,速度更快。
后续补充完整实验对比数据,及完整测试代码。转载请注明出处,谢谢合作。

你可能感兴趣的:(计算机视觉)