自学内容网 自学内容网

海康VM脚本中使用opencvsharp和halcon

最近海康VM用的有点多,但是VM有时候处理复杂图像还是比较难受的,拖拉拽不一定就好,有时候需要加入别的或者已经用opencvsharp写好的一些功能想直接放进VM中。

于是需要在VM脚本中转换halcon opencvsharp VM脚本图像 图像类型之间互相转换。

VM脚本实际上就是Csharp,只要Csharp支持的几乎都可以在VM脚本实现。

我这是一个例子。拿出来。环境配置在注释中体现。

using System.Text;
using System.Windows.Forms;
using Script.Methods;

using System.Runtime.InteropServices;


using System.Threading.Tasks;


using HalconDotNet;
using Ha=HalconDotNet;
using ha=HalconDotNet.HOperatorSet;

using OpenCvSharp;
using OpenCvSharp.Extensions;


using System.Drawing; //添加引用System.Drawing.dll
using System.Drawing.Imaging;

using HslCommunication;
using HslCommunication.LogNet;

using CSINIRW;
//ini 文件操作类


//using HslCommunication.Profinet.Melsec;


// 提示:关闭脚本窗口后:在VM流程中 鼠标选中脚本模块,按Ctrl+M快捷键,可以直接跳转到脚本模块目录。
//C:\Program Files\VisionMaster4.3.0\Applications\Module(sp)\x64\Logic\ShellModule\DLL
//复制 halcon的dll     包括依赖dll
//复制 OpenCvSharp dll 包括依赖dll
//复制 hslcomm dll
//复制 csini

// vm自带 OpenCvSharp路径
//C:\Program Files\VisionMaster4.3.0\Applications\3rdLib\OpenCv
//编辑程序集> 引用需要的dll


/*****************************************************************
输入变量:
int0 (IMAGE) 1 图象源1.图像[]

输出变量:
out0 (IMAGE)
out0 (IMAGE)
************************************************************************/


public partial class UserScript:ScriptMethods,IProcessMethods
{

//执行次数计数
    int processCount ;  
    
    public void Init()
    {
        processCount = 0;
    }

    public bool Process()
    {

//--------------------------------------------------------------------------------------------------------------------------------------------
//VM:脚本输入图像(图像类型是ImageData); 
ImageData img    = new ImageData();     //实例化ImageData类型图像. 海康ImageData;Cv.Mat;
ImageData imgOut = new ImageData();  //输入图像无数据会出现调用失败的情况>>( Line:0 -- Error:编译错误:方法执行失败 Init(),调用的目标发生了异常。); //输入图像需要订阅才会有数据;;
//ImageData imgOutC = new ImageData();


GetImageValue("in0",ref img);      //读取输入图像;






Mat matimg = ImageDataToMat(img);  // 脚本图像转  Mat;

double maxValue=239;
Mat dst = new Mat();
Mat dst1= new Mat();





 //Mat src = new Mat(@"lena2.jpg", ImreadModes.Grayscale);//exe同目录图片
 
  
        Cv2.Canny(matimg, dst, 15, 200);

        
        // opencv 自适应阈值 
        Cv2.AdaptiveThreshold(matimg, dst1, 255,OpenCvSharp.AdaptiveThresholdTypes.MeanC, OpenCvSharp.ThresholdTypes.Binary, 11, 2);
        /*******
        Cv2.AdaptiveThreshold(Mat src, Mat dst, double maxValue, 
                      AdaptiveThresholdTypes adaptiveMethod, 
                      ThresholdTypes thresholdType, int blockSize, double C);

        
Mat src:输入图像。
Mat dst:输出图像,与输入图像 src 具有相同的大小和类型。
double maxValue:当像素值大于阈值时,将其设置为的值。
AdaptiveThresholdTypes adaptiveMethod:自适应方法的类型,决定如何计算局部阈值。
AdaptiveThresholdTypes.MeanC:计算邻域块的均值,阈值为均值减去常量 C。
AdaptiveThresholdTypes.GaussianC:计算邻域块的加权和,权重由高斯窗口确定,阈值为和减去常量 C。
*******/



// 测试临时可以快速看到图 实际过程中 会导致
//*******/
// //这里演示VM脚本>OpencvSharp 窗口显示
Task.Run(() =>{
using (new Window("dst1_Image", WindowMode.Normal, dst1))
{
 Cv2.WaitKey(0);
}
});
//*******/

//*********
//这里演示VM脚本>halcon 窗口显示

Task.Run(() =>{
HObject ho_Image;
HTuple Heigh,Width;
HTuple hv_WindowHandle = new HTuple();
Mat imageROI = new Mat(matimg,new Rect(0,0,260,260));//设置Roi
imgOut = MatToImageData(matimg);//Mat 转脚本图像
HObject himg = ImageDataToHalconImage(img);
ha.ReadImage(out ho_Image, "printer_chip/printer_chip_01");
ho_Image=himg;
ha.GetImageSize(ho_Image,out Heigh,out Width);
ha.SetSystem("use_window_thread","true"); // 不开这个 vm运行脚本后ha窗口会卡死
ha.OpenWindow(0,0,512,512,0,"visible","",out hv_WindowHandle); //开这个窗口就会一闪而过
ha.SetPart(hv_WindowHandle,0,0,Width,Heigh);
ha.DispObj(ho_Image,hv_WindowHandle);
Sleep(3000);// 时间越长 halcon窗口关闭越慢 测试用 不能在VM脚本瞎搞
});


//*******/


//Mat dstImage = Mat.Zeros(imageROI.Width,imageROI.Width,MatType.CV_8UC1);//调用OpenCV接口进行图像处理


// Mat src = Cv2.ImRead(@"C:/Users/Administrator/Desktop/lenapic/lena2.jpg", ImreadModes.Grayscale);

//Cv2.Threshold(imageROI,dstImage,10,120,ThresholdTypes.Otsu);//二值化

//画线
//    Point p1 = new Point(0, 0);
    //        Point p2;
    //        p2.X = 260;
    //        p2.Y = 260;
    //        Scalar color = new Scalar(255, 0, 255);
            //Cv2.Line(dstImage, p1, p2, color, 2, LineTypes.Link8);

            
         //画框
//Rect rect1 = new Rect(0, 0, 260, 260);
//Scalar color1 = new Scalar(255, 0, 0);
//Cv2.Rectangle(dstImage, rect1, color1, 2, LineTypes.AntiAlias);//LineTypes.AntiAlias:反锯齿效果

//写字
//string str001="OpenCV:";
//Cv2.PutText(dstImage,str001, new Point(10,30), HersheyFonts.HersheySimplex, 1,Scalar.All(255),1,LineTypes.Link4);
//Cv2.PutText(srcImage,"srcImage:", new Point(300,300), HersheyFonts.HersheySimplex, 1,Scalar.All(255),1,LineTypes.Link4);

               // using (src = new Mat(@"C:\Users\whx\Desktop\opcvImage\s1.jpg", ImreadModes.AnyColor | ImreadModes.AnyDepth))
               // Mat dst = new Mat(src.Size(),src.Type());
               //src.CopyTo(dst);
              //  using (new Window("DST Image", WindowMode.Normal, matimg))
               // using (new Window("SRC Image", WindowMode.Normal, src))







//将处理后的图像拷贝到原图ROI区域

        SetImageValue("out0",imgOut);//输出图像

//--------------------------------------------------------------------------------------------------------------------------------------------
/*****************************************************************************************************************************************/


        return true;
    }

//--------------------------------------------------------------------------------------------------------------------------------------------
/*****************************************************************************************************************************************/
    // ImageDataToMat
    // MatToImageData
  // HalconImageToImageData
    // ImageDataToHalconImage
public Mat ImageDataToMat(ImageData img)
{
    Mat matImage = new Mat();
    if(ImagePixelFormate.MONO8 == img.PixelFormat)
    {
        matImage = Mat.Zeros(img.Heigth, img.Width, MatType.CV_8UC1);
        IntPtr grayPtr = Marshal.AllocHGlobal(img.Width * img.Heigth);
        Marshal.Copy(img.Buffer, 0, matImage.Ptr(0), img.Buffer.Length);

        //用完记得释放指针 
        Marshal.FreeHGlobal(grayPtr);
    }
    else if (ImagePixelFormate.RGB24 == img.PixelFormat)
    {
        matImage = Mat.Zeros(img.Heigth, img.Width, MatType.CV_8UC3);
        IntPtr rgbPtr = Marshal.AllocHGlobal(img.Width * img.Heigth * 3);
        Marshal.Copy(img.Buffer, 0, matImage.Ptr(0), img.Buffer.Length);
        Cv2.CvtColor(matImage, matImage, ColorConversionCodes.RGB2BGR);

        //用完记得释放指针 
        Marshal.FreeHGlobal(rgbPtr);
    }
    return matImage;
}

public ImageData MatToImageData(Mat matImage)
{
    ImageData imgOut = new ImageData();
    byte[] buffer = new Byte[matImage.Width * matImage.Height * matImage.Channels()];
    Marshal.Copy(matImage.Ptr(0), buffer, 0, buffer.Length);
    if (1 == matImage.Channels())
    {
        imgOut.Buffer = buffer;
        imgOut.Width = matImage.Width;
        imgOut.Heigth = matImage.Height;
        imgOut.PixelFormat = ImagePixelFormate.MONO8;
    }
    else if (3 == matImage.Channels())
    {
        //交换R与B通道
        for (int i = 0; i < buffer.Length - 2; i += 3)
        {
            byte temp = buffer[i];
            buffer[i] = buffer[i + 2];
            buffer[i + 2] = temp;
        }

        imgOut.Buffer = buffer;
        imgOut.Width = matImage.Width;
        imgOut.Heigth = matImage.Height;
        imgOut.PixelFormat = ImagePixelFormate.RGB24;
    }
    return imgOut;
}
 
//halcon图像与脚本图像(ImageData)互转 
//HalconImageToImageData
    //ImageDataToHalconImage
public static ImageData HalconImageToImageData(HObject hImageObj)
{
    try
    {
        ImageData imageData = new ImageData();
        HTuple imageWidth = 0;
        HTuple imageHeight = 0;
        HTuple objClass = hImageObj.GetObjClass();
        if (objClass.S.Equals("image"))
        {
            HTuple imageType;
            HOperatorSet.GetImageType(hImageObj, out imageType);
            if (imageType.S.Equals("byte"))
            {
                //获取图像通道数
                HTuple channels = 0;
                HOperatorSet.CountChannels(hImageObj, out channels);
                //如果是单通道
                if (channels.I == 1)
                {
                    HTuple imagePointer;
                    HOperatorSet.GetImagePointer1(hImageObj, out imagePointer, out imageType, out imageWidth, out imageHeight);
                    imageData.Width = imageWidth.I;
                    imageData.Heigth = imageHeight.I;
                    imageData.PixelFormat = ImagePixelFormate.MONO8;
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    imageData.Buffer = new byte[stride * imageHeight.I];
                    Marshal.Copy(imagePointer, imageData.Buffer, 0, stride * imageHeight.I);
                }
                //如果是三通道
                else if (channels.I == 3)
                {
                    HTuple redChannel;
                    HTuple greenChannel;
                    HTuple blueChannel;
                    HOperatorSet.GetImagePointer3(hImageObj, out redChannel, out greenChannel, out blueChannel, out imageType, out imageWidth, out imageHeight);
                    imageData.Width = imageWidth.I;
                    imageData.Heigth = imageHeight.I;
                    imageData.PixelFormat = ImagePixelFormate.RGB24;
                    int stride = imageWidth.I;
                    if (stride % 4 != 0)
                    {
                        stride += 4 - stride % 4;
                    }
                    imageData.Buffer = new byte[stride * imageHeight.I * 3];
                    byte[] imageRedBuffer = new byte[stride * imageHeight.I];
                    byte[] imageGreenBuffer = new byte[stride * imageHeight.I];
                    byte[] imageBlueBuffer = new byte[stride * imageHeight.I];
                    Marshal.Copy(redChannel.IP, imageRedBuffer, 0, imageRedBuffer.Length);
                    Marshal.Copy(greenChannel.IP, imageGreenBuffer, 0, imageGreenBuffer.Length);
                    Marshal.Copy(blueChannel.IP, imageBlueBuffer, 0, imageBlueBuffer.Length);
                    for (int row = 0; row < imageHeight.I; row++)
                    {
                        for (int col = 0, index = 0; col < imageWidth.I; col++, index += 3)
                        {
                            imageData.Buffer[index] = imageRedBuffer[row * imageWidth + col];
                            imageData.Buffer[index + 1] = imageGreenBuffer[row * imageWidth + col];
                            imageData.Buffer[index + 2] = imageBlueBuffer[row * imageWidth + col];
                        }
                    }
                }
                else
                {
                    hImageObj.Dispose();
                    throw new Exception("不支持单通道,三通道以外的图像");
                }
            }
            else
            {
                hImageObj.Dispose();
                throw new Exception("不支持8bit以外的位深度图像");
            }
        }
        else
        {
            hImageObj.Dispose();
            throw new Exception("HObject非图像类型对象");
        }
        return imageData;
    }
    catch (Exception ex)
    {
        hImageObj.Dispose();
        throw new Exception(ex.Message);
    }
}

public static HObject ImageDataToHalconImage(ImageData image)
{
    IntPtr imagePointer = IntPtr.Zero;
    IntPtr redChannel = IntPtr.Zero;
    IntPtr greenChannel = IntPtr.Zero;
    IntPtr blueChannel = IntPtr.Zero;
    try
    {
        HObject imageObj = new HObject();
        HTuple width = image.Width;
        HTuple height = image.Heigth;
        if (image.PixelFormat == ImagePixelFormate.MONO8)
        {
            imagePointer = Marshal.AllocHGlobal(image.Buffer.Length);
            Marshal.Copy(image.Buffer, 0, imagePointer, image.Buffer.Length);
            HOperatorSet.GenImage1(out imageObj, "byte", width, height, imagePointer);
        }
        else if (image.PixelFormat == ImagePixelFormate.RGB24)
        {
            byte[] imageRedBuffer = new byte[image.Buffer.Length / 3];
            byte[] imageGreBuffer = new byte[image.Buffer.Length / 3];
            byte[] imageBluBuffer = new byte[image.Buffer.Length / 3];
            int index = 0;
            for (int i = 0; i < image.Buffer.Length; index++, i += 3)
            {
                imageRedBuffer[index] = image.Buffer[i];
                imageGreBuffer[index] = image.Buffer[i + 1];
                imageBluBuffer[index] = image.Buffer[i + 2];
            }
            redChannel = Marshal.AllocHGlobal(imageRedBuffer.Length);
            greenChannel = Marshal.AllocHGlobal(imageGreBuffer.Length);
            blueChannel = Marshal.AllocHGlobal(imageBluBuffer.Length);
            Marshal.Copy(imageRedBuffer, 0, redChannel, imageRedBuffer.Length);
            Marshal.Copy(imageGreBuffer, 0, greenChannel, imageGreBuffer.Length);
            Marshal.Copy(imageBluBuffer, 0, blueChannel, imageBluBuffer.Length);
            HOperatorSet.GenImage3(out imageObj, "byte", width, height, redChannel, greenChannel, blueChannel);
        }
        return imageObj;
    }
    catch (Exception ex)
    {
        Marshal.FreeHGlobal(imagePointer);
        Marshal.FreeHGlobal(redChannel);
        Marshal.FreeHGlobal(greenChannel);
        Marshal.FreeHGlobal(blueChannel);
        throw new Exception(ex.Message);
    }
}



//

///
///

        public void Mat2HObjectBpp8_u(Mat mat, out HObject image)
        {
            int ImageWidth = mat.Width;
            int ImageHeight = mat.Height;
            int channel = mat.Channels();
            long size = ImageWidth * ImageHeight * channel;
            int col_byte_num = ImageWidth * channel;

            byte[] rgbValues = new byte[size];
            //IntPtr imgptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(rgbValues.Length);
            unsafe
            {
                for (int i = 0; i < mat.Height; i++)
                {
                    IntPtr c = mat.Ptr(i);
                    //byte* c1 = (byte*)c;
                    System.Runtime.InteropServices.Marshal.Copy(c, rgbValues, i * col_byte_num, col_byte_num); // 一行一行将mat 像素复制到byte[], 
                }

                void* p;
                IntPtr ptr;
                fixed (byte* pc = rgbValues)
                {
                    p = (void*)pc;
                    ptr = new IntPtr(p);

                }

                HOperatorSet.GenImage1(out image, "byte", ImageWidth, ImageHeight, ptr);
            }

        }

        public void Mat2HObjectBpp24_u(Mat mat, out HObject image)
        {
            int ImageWidth = mat.Width;
            int ImageHeight = mat.Height;
            int channel = mat.Channels();
            long size = ImageWidth * ImageHeight * channel;
            int col_byte_num = ImageWidth * channel;

            byte[] rgbValues = new byte[size];
            //IntPtr imgptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(rgbValues.Length);
            unsafe
            {
                for (int i = 0; i < mat.Height; i++)
                {
                    IntPtr c = mat.Ptr(i);
                    //byte* c1 = (byte*)c;
                    System.Runtime.InteropServices.Marshal.Copy(c, rgbValues, i * col_byte_num, col_byte_num);
                }

                void* p;
                IntPtr ptr;
                fixed (byte* pc = rgbValues)
                {
                    p = (void*)pc;
                    ptr = new IntPtr(p);

                }
                HOperatorSet.GenImageInterleaved(out image, ptr, "bgr", ImageWidth, ImageHeight, 0, "byte", 0, 0, 0, 0, -1, 0);

            }

        }




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

        //两个方向4个函数 m2h h2m 

        /// <summary>
        /// /
        /// </summary>
        /// <param name="mat"></param>
        /// <param name="image"></param>


        static void Mat2HObjectBpp8(Mat mat, out HObject image) 
        {
            try
            {
                Bitmap bmp = mat.ToBitmap();        
                Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                BitmapData srcBmpData = bmp.LockBits(rect,ImageLockMode.ReadOnly,PixelFormat.Format8bppIndexed);
                HOperatorSet.GenImage1(out image,"byte",bmp.Width,bmp.Height,srcBmpData.Scan0);
                bmp.UnlockBits(srcBmpData);
            }
            catch(Exception ex)
            {
                image = null;
            }
        }
        static void Mat2HObjectBpp24(Mat mat,out  HObject image)
        {

            Bitmap bmp = mat.ToBitmap();
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            BitmapData srcBmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            //    HOperatorSet.GenImageInterleaved(out image,srcBmpData.Scan0, "bgr", bmp.Width, bmp.Height,"byte" ,0,0,0,0,-1,0,0);
           // HOperatorSet.GenImageInterleaved(out image, srcBmpData.Scan0, "bgr", bmp.Width, bmp.Height, 0, "byte", 0,0, 0, 0, -1, 2);
            HOperatorSet.GenImageInterleaved(out image, srcBmpData.Scan0, "bgr", bmp.Width, bmp.Height, 0, "byte", 0, 0, 0, 0, -1, 0);


            bmp.UnlockBits(srcBmpData);

        }

        static void HObject2Mat8(HObject image ,out  Mat res) 
        {//ok
            HTuple hpoint, type, width, height;
            HOperatorSet.GetImagePointer1(image ,out hpoint,out type,out width,out height);
            IntPtr ptr2 = hpoint;
            int bytes = width * height;
            byte[] rgbvalues = new byte[bytes];
            System.Runtime.InteropServices.Marshal.Copy(ptr2,rgbvalues,0,bytes);
            res = new Mat(height,width,MatType.CV_8UC1,rgbvalues);
        
        }
        static void HObject2Mat24(HObject image,out Mat res)
        {
            // ok
            HTuple hred,hgreen,hblue , type, width, height;
            HOperatorSet.GetImagePointer3
                (image,out hred,out hgreen,out hblue ,out type,out width,out height);
            int bytes = width * height;
            byte[] rvalues = new byte[bytes];
            byte[] gvalues = new byte[bytes];
            byte[] bvalues = new byte[bytes];
            IntPtr ptrr = hred;
            IntPtr ptrg = hgreen;
            IntPtr ptrb = hblue;
            Mat resr, resg, resb;


            System.Runtime.InteropServices.Marshal.Copy(ptrr, rvalues, 0, bytes);
            resr = new Mat(height, width, MatType.CV_8UC1, rvalues);
           
            System.Runtime.InteropServices.Marshal.Copy(ptrg, gvalues, 0, bytes);
            resg = new Mat(height, width, MatType.CV_8UC1, gvalues);
           
            System.Runtime.InteropServices.Marshal.Copy(ptrb, bvalues, 0, bytes);
            resb = new Mat(height, width, MatType.CV_8UC1, bvalues);

            Mat[] mv = new Mat[3] { resb,resg,resr };
            res = new Mat();
            Cv2.Merge(mv, res);
    
        }



   
}

看函数名就知道是干嘛用的了,填参数就行。

当然转换专题还没有完全结束 后面心情好的时候继续更新。

下一步打算把python的numpy图像塞进VM中,至此VM就可以拥有python图像处理的一切功能,也可以重复利用手上现有的python程序。


原文地址:https://blog.csdn.net/u014584014/article/details/142372542

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!