海康VM脚本中使用opencvsharp和halcon

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

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

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

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

cs 复制代码
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程序。

相关推荐
秋秋秋叶2 小时前
【2】图像视频的加载和显示
opencv·学习
—你的鼬先生2 小时前
从零开始使用树莓派debian系统使用opencv4.10.0进行人脸识别(保姆级教程)
python·opencv·debian·人脸识别·二维码识别·opencv安装
憨憨憨憨憨到不行的程序员3 小时前
【OpenCV】场景中人的识别与前端计数
人工智能·opencv·计算机视觉
剑指~巅峰3 小时前
亲身体验Llama 3.1:开源模型的部署与应用之旅
人工智能·深度学习·opencv·机器学习·计算机视觉·数据挖掘·llama
AI视觉网奇4 小时前
两个多边形 贴图
python·opencv·贴图
CV-King9 小时前
计算机视觉硬件整理(四):相机与镜头参数介绍
图像处理·人工智能·数码相机·opencv·计算机视觉
jndingxin11 小时前
OpenCV图像文件读写(6)将图像数据写入文件的函数imwrite()的使用
人工智能·opencv·计算机视觉
lilihewo11 小时前
Android使用OpenCV 4.5.0实现扑克牌识别(源码分享)
人工智能·opencv·计算机视觉
噗 嗤13 小时前
java调用opencv部署到centos7
java·linux·opencv
jndingxin1 天前
OpenCV特征检测(10)检测图像中直线的函数HoughLinesP()的使用
人工智能·opencv·计算机视觉