简单的来说,就是将

一类的图片最后拼接成为这样的结果

这个图片有点大呀。

基本步骤:

1、halcon进行仿射变化进行镜头畸变。这个可以参考halcon中一个二维码畸变的例子;

2、基于模版匹配找出偏移值,然后进行拼接。这个可以参考halcon中一个拼接的例子;

3、对交接处进行融合,这个是本文的关键。

首先,这个融合halcon中是没有方法的,所以要自己实现。首先要看论文《基于Halcon的图像拼接算法研究_谭杰》。然后文中有两种方法,因为本例没有产生旋转,所以采用第一种就可以。融合部分代码如下

for i:=RowStart to RowEnd by 1
    for j:=450 to 1560 by 1
        get_grayval(Imageresult1, i,100, Grayval1)
        get_grayval(Imageresult2, i, 100, Grayval2)
        grayval0 := (Grayval1 * yinzhi + Grayval2 * (100-yinzhi))/100
        set_grayval(Imageresult0, i, j, grayval0)
    endfor
    yinzhi := yinzhi -1
endfor

接下来就是效率问题,由于halcon是高级语言,为了提高效率,需要在csharp中直接操作内存,进行类似的操作。所以需要将这段代码改写成为csharp的形式。代码如下

using System;
using System.Collections.Generic;
using System.Text;
//新添加
using HalconDotNet;

//2013年10月24日14:54:09 所有图片融和的重构
namespace Halcon10test
{
    public  class  HalconHepler
    {
       
#region 停止HDevelopStop
        public void HDevelopStop()
        {
        }
#endregion
#region 显示继续信息 disp_continue_message    
        public void disp_continue_message(HTuple hv_WindowHandle, HTuple hv_Color, HTuple hv_Box)
        {

HTuple hv_ContinueMessage, hv_Row, hv_Column;
            HTuple hv_Width, hv_Height, hv_Ascent, hv_Descent, hv_TextWidth;
            HTuple hv_TextHeight;
            hv_ContinueMessage = "按下(F5)程序将继续";
            HOperatorSet.GetWindowExtents(hv_WindowHandle, out hv_Row, out hv_Column, out hv_Width,
                out hv_Height);
            HOperatorSet.GetStringExtents(hv_WindowHandle, (" " + hv_ContinueMessage) + " ",
                out hv_Ascent, out hv_Descent, out hv_TextWidth, out hv_TextHeight);
            disp_message(hv_WindowHandle, hv_ContinueMessage, "window", (hv_Height - hv_TextHeight) - 12,
                (hv_Width - hv_TextWidth) - 12, hv_Color, hv_Box);

return;
        }
#endregion
#region 显示信息
        public void disp_message(HTuple hv_WindowHandle, HTuple hv_String, HTuple hv_CoordSystem,
            HTuple hv_Row, HTuple hv_Column, HTuple hv_Color, HTuple hv_Box)
        {
            HTuple hv_Red, hv_Green, hv_Blue, hv_Row1Part;
            HTuple hv_Column1Part, hv_Row2Part, hv_Column2Part, hv_RowWin;
            HTuple hv_ColumnWin, hv_WidthWin, hv_HeightWin, hv_MaxAscent;
            HTuple hv_MaxDescent, hv_MaxWidth, hv_MaxHeight, hv_R1 = new HTuple();
            HTuple hv_C1 = new HTuple(), hv_FactorRow = new HTuple(), hv_FactorColumn = new HTuple();
            HTuple hv_Width = new HTuple(), hv_Index = new HTuple(), hv_Ascent = new HTuple();
            HTuple hv_Descent = new HTuple(), hv_W = new HTuple(), hv_H = new HTuple();
            HTuple hv_FrameHeight = new HTuple(), hv_FrameWidth = new HTuple();
            HTuple hv_R2 = new HTuple(), hv_C2 = new HTuple(), hv_DrawMode = new HTuple();
            HTuple hv_Exception = new HTuple(), hv_CurrentColor = new HTuple();

HTuple hv_Color_COPY_INP_TMP = hv_Color.Clone();
            HTuple hv_Column_COPY_INP_TMP = hv_Column.Clone();
            HTuple hv_Row_COPY_INP_TMP = hv_Row.Clone();
            HTuple hv_String_COPY_INP_TMP = hv_String.Clone();

HOperatorSet.GetRgb(hv_WindowHandle, out hv_Red, out hv_Green, out hv_Blue);
            HOperatorSet.GetPart(hv_WindowHandle, out hv_Row1Part, out hv_Column1Part, out hv_Row2Part,
                out hv_Column2Part);
            HOperatorSet.GetWindowExtents(hv_WindowHandle, out hv_RowWin, out hv_ColumnWin,
                out hv_WidthWin, out hv_HeightWin);
            HOperatorSet.SetPart(hv_WindowHandle, 0, 0, hv_HeightWin - 1, hv_WidthWin - 1);
            //
            //default settings
            if ((int)(new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(-1))) != 0)
            {
                hv_Row_COPY_INP_TMP = 12;
            }
            if ((int)(new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(-1))) != 0)
            {
                hv_Column_COPY_INP_TMP = 12;
            }
            if ((int)(new HTuple(hv_Color_COPY_INP_TMP.TupleEqual(new HTuple()))) != 0)
            {
                hv_Color_COPY_INP_TMP = "";
            }
            //
            hv_String_COPY_INP_TMP = ((("" + hv_String_COPY_INP_TMP) + "")).TupleSplit("\n");
            //
            //Estimate extentions of text depending on font size.
            HOperatorSet.GetFontExtents(hv_WindowHandle, out hv_MaxAscent, out hv_MaxDescent,
                out hv_MaxWidth, out hv_MaxHeight);
            if ((int)(new HTuple(hv_CoordSystem.TupleEqual("window"))) != 0)
            {
                hv_R1 = hv_Row_COPY_INP_TMP.Clone();
                hv_C1 = hv_Column_COPY_INP_TMP.Clone();
            }
            else
            {
                //transform image to window coordinates
                hv_FactorRow = (1.0 * hv_HeightWin) / ((hv_Row2Part - hv_Row1Part) + 1);
                hv_FactorColumn = (1.0 * hv_WidthWin) / ((hv_Column2Part - hv_Column1Part) + 1);
                hv_R1 = ((hv_Row_COPY_INP_TMP - hv_Row1Part) + 0.5) * hv_FactorRow;
                hv_C1 = ((hv_Column_COPY_INP_TMP - hv_Column1Part) + 0.5) * hv_FactorColumn;
            }
            //
            //display text box depending on text size
            if ((int)(new HTuple(hv_Box.TupleEqual("true"))) != 0)
            {
                //calculate box extents
                hv_String_COPY_INP_TMP = (" " + hv_String_COPY_INP_TMP) + " ";
                hv_Width = new HTuple();
                for (hv_Index = 0; (int)hv_Index <= (int)((new HTuple(hv_String_COPY_INP_TMP.TupleLength()
                    )) - 1); hv_Index = (int)hv_Index + 1)
                {
                    HOperatorSet.GetStringExtents(hv_WindowHandle, hv_String_COPY_INP_TMP.TupleSelect(
                        hv_Index), out hv_Ascent, out hv_Descent, out hv_W, out hv_H);
                    hv_Width = hv_Width.TupleConcat(hv_W);
                }
                hv_FrameHeight = hv_MaxHeight * (new HTuple(hv_String_COPY_INP_TMP.TupleLength()
                    ));
                hv_FrameWidth = (((new HTuple(0)).TupleConcat(hv_Width))).TupleMax();
                hv_R2 = hv_R1 + hv_FrameHeight;
                hv_C2 = hv_C1 + hv_FrameWidth;
                //display rectangles
                HOperatorSet.GetDraw(hv_WindowHandle, out hv_DrawMode);
                HOperatorSet.SetDraw(hv_WindowHandle, "fill");
                HOperatorSet.SetColor(hv_WindowHandle, "light gray");
                HOperatorSet.DispRectangle1(hv_WindowHandle, hv_R1 + 3, hv_C1 + 3, hv_R2 + 3, hv_C2 + 3);
                HOperatorSet.SetColor(hv_WindowHandle, "white");
                HOperatorSet.DispRectangle1(hv_WindowHandle, hv_R1, hv_C1, hv_R2, hv_C2);
                HOperatorSet.SetDraw(hv_WindowHandle, hv_DrawMode);
            }
            else if ((int)(new HTuple(hv_Box.TupleNotEqual("false"))) != 0)
            {
                hv_Exception = "Wrong value of control parameter Box";
                throw new HalconException(hv_Exception);
            }
            //Write text.
            for (hv_Index = 0; (int)hv_Index <= (int)((new HTuple(hv_String_COPY_INP_TMP.TupleLength()
                )) - 1); hv_Index = (int)hv_Index + 1)
            {
                hv_CurrentColor = hv_Color_COPY_INP_TMP.TupleSelect(hv_Index % (new HTuple(hv_Color_COPY_INP_TMP.TupleLength()
                    )));
                if ((int)((new HTuple(hv_CurrentColor.TupleNotEqual(""))).TupleAnd(new HTuple(hv_CurrentColor.TupleNotEqual(
                    "auto")))) != 0)
                {
                    HOperatorSet.SetColor(hv_WindowHandle, hv_CurrentColor);
                }
                else
                {
                    HOperatorSet.SetRgb(hv_WindowHandle, hv_Red, hv_Green, hv_Blue);
                }
                hv_Row_COPY_INP_TMP = hv_R1 + (hv_MaxHeight * hv_Index);
                HOperatorSet.SetTposition(hv_WindowHandle, hv_Row_COPY_INP_TMP, hv_C1);
                HOperatorSet.WriteString(hv_WindowHandle, hv_String_COPY_INP_TMP.TupleSelect(
                    hv_Index));
            }
            //reset changed window settings
            HOperatorSet.SetRgb(hv_WindowHandle, hv_Red, hv_Green, hv_Blue);
            HOperatorSet.SetPart(hv_WindowHandle, hv_Row1Part, hv_Column1Part, hv_Row2Part,
                hv_Column2Part);

return;
        }
#endregion
#region 设置字体

public void set_display_font(HTuple hv_WindowHandle, HTuple hv_Size, HTuple hv_Font,
            HTuple hv_Bold, HTuple hv_Slant)
        {
            HTuple hv_OS, hv_Exception = new HTuple();
            HTuple hv_AllowedFontSizes = new HTuple(), hv_Distances = new HTuple();
            HTuple hv_Indices = new HTuple();

HTuple hv_Bold_COPY_INP_TMP = hv_Bold.Clone();
            HTuple hv_Font_COPY_INP_TMP = hv_Font.Clone();
            HTuple hv_Size_COPY_INP_TMP = hv_Size.Clone();
            HTuple hv_Slant_COPY_INP_TMP = hv_Slant.Clone();

HOperatorSet.GetSystem("operating_system", out hv_OS);
            if ((int)((new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(new HTuple()))).TupleOr(
                new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(-1)))) != 0)
            {
                hv_Size_COPY_INP_TMP = 16;
            }
            if ((int)(new HTuple((((hv_OS.TupleStrFirstN(2)).TupleStrLastN(0))).TupleEqual(
                "Win"))) != 0)
            {
                //set font on Windows systems
                if ((int)((new HTuple((new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("mono"))).TupleOr(
                    new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("Courier"))))).TupleOr(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual(
                    "courier")))) != 0)
                {
                    hv_Font_COPY_INP_TMP = "Courier New";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("sans"))) != 0)
                {
                    hv_Font_COPY_INP_TMP = "Arial";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("serif"))) != 0)
                {
                    hv_Font_COPY_INP_TMP = "Times New Roman";
                }
                if ((int)(new HTuple(hv_Bold_COPY_INP_TMP.TupleEqual("true"))) != 0)
                {
                    hv_Bold_COPY_INP_TMP = 1;
                }
                else if ((int)(new HTuple(hv_Bold_COPY_INP_TMP.TupleEqual("false"))) != 0)
                {
                    hv_Bold_COPY_INP_TMP = 0;
                }
                else
                {
                    hv_Exception = "Wrong value of control parameter Bold";
                    throw new HalconException(hv_Exception);
                }
                if ((int)(new HTuple(hv_Slant_COPY_INP_TMP.TupleEqual("true"))) != 0)
                {
                    hv_Slant_COPY_INP_TMP = 1;
                }
                else if ((int)(new HTuple(hv_Slant_COPY_INP_TMP.TupleEqual("false"))) != 0)
                {
                    hv_Slant_COPY_INP_TMP = 0;
                }
                else
                {
                    hv_Exception = "Wrong value of control parameter Slant";
                    throw new HalconException(hv_Exception);
                }
                try
                {
                    HOperatorSet.SetFont(hv_WindowHandle, ((((((("-" + hv_Font_COPY_INP_TMP) + "-") + hv_Size_COPY_INP_TMP) + "-*-") + hv_Slant_COPY_INP_TMP) + "-*-*-") + hv_Bold_COPY_INP_TMP) + "-");
                }
                // catch (Exception)
                catch (HalconException HDevExpDefaultException1)
                {
                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
                    throw new HalconException(hv_Exception);
                }
            }
            else
            {
                //set font for UNIX systems
                hv_Size_COPY_INP_TMP = hv_Size_COPY_INP_TMP * 1.25;
                hv_AllowedFontSizes = new HTuple();
                hv_AllowedFontSizes[0] = 11;
                hv_AllowedFontSizes[1] = 14;
                hv_AllowedFontSizes[2] = 17;
                hv_AllowedFontSizes[3] = 20;
                hv_AllowedFontSizes[4] = 25;
                hv_AllowedFontSizes[5] = 34;
                if ((int)(new HTuple(((hv_AllowedFontSizes.TupleFind(hv_Size_COPY_INP_TMP))).TupleEqual(
                    -1))) != 0)
                {
                    hv_Distances = ((hv_AllowedFontSizes - hv_Size_COPY_INP_TMP)).TupleAbs();
                    HOperatorSet.TupleSortIndex(hv_Distances, out hv_Indices);
                    hv_Size_COPY_INP_TMP = hv_AllowedFontSizes.TupleSelect(hv_Indices.TupleSelect(
                        0));
                }
                if ((int)((new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("mono"))).TupleOr(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual(
                    "Courier")))) != 0)
                {
                    hv_Font_COPY_INP_TMP = "courier";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("sans"))) != 0)
                {
                    hv_Font_COPY_INP_TMP = "helvetica";
                }
                else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("serif"))) != 0)
                {
                    hv_Font_COPY_INP_TMP = "times";
                }
                if ((int)(new HTuple(hv_Bold_COPY_INP_TMP.TupleEqual("true"))) != 0)
                {
                    hv_Bold_COPY_INP_TMP = "bold";
                }
                else if ((int)(new HTuple(hv_Bold_COPY_INP_TMP.TupleEqual("false"))) != 0)
                {
                    hv_Bold_COPY_INP_TMP = "medium";
                }
                else
                {
                    hv_Exception = "Wrong value of control parameter Bold";
                    throw new HalconException(hv_Exception);
                }
                if ((int)(new HTuple(hv_Slant_COPY_INP_TMP.TupleEqual("true"))) != 0)
                {
                    if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("times"))) != 0)
                    {
                        hv_Slant_COPY_INP_TMP = "i";
                    }
                    else
                    {
                        hv_Slant_COPY_INP_TMP = "o";
                    }
                }
                else if ((int)(new HTuple(hv_Slant_COPY_INP_TMP.TupleEqual("false"))) != 0)
                {
                    hv_Slant_COPY_INP_TMP = "r";
                }
                else
                {
                    hv_Exception = "Wrong value of control parameter Slant";
                    throw new HalconException(hv_Exception);
                }
                try
                {
                    HOperatorSet.SetFont(hv_WindowHandle, ((((((("-adobe-" + hv_Font_COPY_INP_TMP) + "-") + hv_Bold_COPY_INP_TMP) + "-") + hv_Slant_COPY_INP_TMP) + "-normal-*-") + hv_Size_COPY_INP_TMP) + "-*-*-*-*-*-*-*");
                }
                // catch (Exception)
                catch (HalconException HDevExpDefaultException1)
                {
                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
                    throw new HalconException(hv_Exception);
                }
            }

return;
        }

#endregion
#region 核心函数
        //核心过程
        public unsafe void action(object objectname)
        {  
            //参数处理
            string filename = (string)objectname;
            string[] str = filename.Split(',');
            string inputname = str[0];
            string outputname = str[1];

if (string.Empty == inputname)
            {
                return;
            }
            if (string.Empty == outputname)
            {
                return;
            }
            //变量定义和初始化
            HObject[] OTemp = new HObject[20];
            long SP_O = 0;
            HObject ho_ImageTemplete, ho_Image1, ho_Image2, ho_ImageTmp;
            HObject ho_Image11, ho_Image22, ho_ModelRegion, ho__TmpRegion;
            HObject ho_TemplateImage, ho_ModelContours, ho_Images1;
            HObject ho_Images2, ho_Black, ho_Imageresult0, ho_Imageresult2;
            HObject ho_Imageresult1;
          
            HTuple hv_Pointer_tmp0, hv_Type_tmp0, hv_Width_tmp0, hv_Height_tmp0;
            HTuple hv_Pointer_tmp1, hv_Type_tmp1, hv_Width_tmp1, hv_Height_tmp1;
            HTuple hv_Pointer_tmp2, hv_Type_tmp2, hv_Width_tmp2, hv_Height_tmp2;
            HTuple hv_HomMat2D, hv_Pointer, hv_Type, hv_Width;
            HTuple hv_Height, hv_ImageFiles, hv_Index, hv_ModelId;
            HTuple hv_Row1, hv_Col1, hv_Angle1, hv_Score1, hv_Row2;
            HTuple hv_Col2, hv_Angle2, hv_Score2, hv_i, hv_H = new HTuple();
            HTuple hv_j = new HTuple(), hv_a = new HTuple(), hv_b = new HTuple();
            HTuple hv_Grayval1 = new HTuple(), hv_Grayval2 = new HTuple();
            HTuple hv_grayval = new HTuple();

HOperatorSet.GenEmptyObj(out ho_ImageTemplete);
            HOperatorSet.GenEmptyObj(out ho_Image1);
            HOperatorSet.GenEmptyObj(out ho_Image2);
            HOperatorSet.GenEmptyObj(out ho_Image11);
            HOperatorSet.GenEmptyObj(out ho_Image22);
            HOperatorSet.GenEmptyObj(out ho_ImageTmp);
            HOperatorSet.GenEmptyObj(out ho_ModelRegion);
            HOperatorSet.GenEmptyObj(out ho__TmpRegion);
            HOperatorSet.GenEmptyObj(out ho_TemplateImage);
            HOperatorSet.GenEmptyObj(out ho_ModelContours);
            HOperatorSet.GenEmptyObj(out ho_Images1);
            HOperatorSet.GenEmptyObj(out ho_Images2);
            HOperatorSet.GenEmptyObj(out ho_Black);
            HOperatorSet.GenEmptyObj(out ho_Imageresult0);
            HOperatorSet.GenEmptyObj(out ho_Imageresult2);
            HOperatorSet.GenEmptyObj(out ho_Imageresult1);

if (HDevWindowStack.IsOpen())
            {
                HOperatorSet.SetDraw(HDevWindowStack.GetActive(), "margin");
            }

//图片序列读取
            HOperatorSet.ListFiles(inputname, ((new HTuple("files")).TupleConcat(
                "follow_links")).TupleConcat("recursive"), out hv_ImageFiles);
            HOperatorSet.TupleRegexpSelect(hv_ImageFiles, (new HTuple("\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima)$")).TupleConcat(
                "ignore_case"), out hv_ImageFiles);
            //if hv_imageFiles.length!=15  这个问题可以下一步考虑

//校正矩阵计算(参数人工设定,也可以机器标定)
            ho_ImageTemplete.Dispose();
            HOperatorSet.ReadImage(out ho_ImageTemplete, hv_ImageFiles.TupleSelect(0));
            HOperatorSet.HomVectorToProjHomMat2d((((new HTuple(0)).TupleConcat(1080)).TupleConcat(
                1080)).TupleConcat(0), (((new HTuple(472)).TupleConcat(327)).TupleConcat(
                1705)).TupleConcat(1543), (((new HTuple(1)).TupleConcat(1)).TupleConcat(1)).TupleConcat(
                1), (((new HTuple(0)).TupleConcat(1080)).TupleConcat(1080)).TupleConcat(0),
                (((new HTuple(472)).TupleConcat(472)).TupleConcat(1546)).TupleConcat(1546),
                (((new HTuple(1)).TupleConcat(1)).TupleConcat(1)).TupleConcat(1), "normalized_dlt",
                out hv_HomMat2D);
            HOperatorSet.GetImagePointer1(ho_ImageTemplete, out hv_Pointer, out hv_Type,
                out hv_Width, out hv_Height);

HOperatorSet.ReadImage(out ho_Image1, hv_ImageFiles.TupleSelect(1));
            ho_Image2.Dispose();
            HOperatorSet.ReadImage(out ho_Image2, hv_ImageFiles.TupleSelect(2));
            ho_Image11.Dispose();
            HOperatorSet.ProjectiveTransImage(ho_Image1, out ho_Image11, hv_HomMat2D, "bilinear",
                "false", "false");
            ho_Image22.Dispose();
            HOperatorSet.ProjectiveTransImage(ho_Image2, out ho_Image22, hv_HomMat2D, "bilinear",
                "false", "false");

OTemp[SP_O] = ho_Image22.CopyObj(1, -1);
            SP_O++;
            ho_Image22.Dispose();
            HOperatorSet.CropPart(OTemp[SP_O - 1], out ho_Image22, 100, 0, hv_Width, hv_Height);
            OTemp[SP_O - 1].Dispose();
            SP_O = 0;

OTemp[SP_O] = ho_Image11.CopyObj(1, -1);
            SP_O++;
            ho_Image11.Dispose();
            HOperatorSet.CropPart(OTemp[SP_O - 1], out ho_Image11, 100, 0, hv_Width, hv_Height);
            OTemp[SP_O - 1].Dispose();
            SP_O = 0;

//通过模板匹配计算得到偏移值
            HOperatorSet.SetSystem("border_shape_models", "false");
            ho_ModelRegion.Dispose();
            HOperatorSet.GenRectangle1(out ho_ModelRegion, 421.374, 1309.12, 521.374, 1415.2);
            ho__TmpRegion.Dispose();
            HOperatorSet.GenRectangle1(out ho__TmpRegion, 902.23, 1041.53, 977.66, 1333.17);
            OTemp[SP_O] = ho_ModelRegion.CopyObj(1, -1);
            SP_O++;
            ho_ModelRegion.Dispose();
            HOperatorSet.Union2(OTemp[SP_O - 1], ho__TmpRegion, out ho_ModelRegion);
            OTemp[SP_O - 1].Dispose();
            SP_O = 0;

ho_TemplateImage.Dispose();
            HOperatorSet.ReduceDomain(ho_Image11, ho__TmpRegion, out ho_TemplateImage);

HOperatorSet.CreateShapeModel(ho_TemplateImage, 4, (new HTuple(0)).TupleRad()
                , (new HTuple(360)).TupleRad(), (new HTuple(0.7706)).TupleRad(), (new HTuple("point_reduction_high")).TupleConcat(
                "no_pregeneration"), "use_polarity", ((new HTuple(21)).TupleConcat(33)).TupleConcat(
                5), 16, out hv_ModelId);

ho_ModelContours.Dispose();
            HOperatorSet.GetShapeModelContours(out ho_ModelContours, hv_ModelId, 1);

HOperatorSet.FindShapeModel(ho_Image11, hv_ModelId, (new HTuple(0)).TupleRad()
                , (new HTuple(0)).TupleRad(), 0.5, 1, 0.5, "least_squares", 4, 0.75, out hv_Row1,
                out hv_Col1, out hv_Angle1, out hv_Score1);

HOperatorSet.FindShapeModel(ho_Image22, hv_ModelId, (new HTuple(0)).TupleRad()
                , (new HTuple(0)).TupleRad(), 0.1, 1, 0.5, "least_squares", 4, 0.75, out hv_Row2,
                out hv_Col2, out hv_Angle2, out hv_Score2);
            HOperatorSet.ClearShapeModel(hv_ModelId);
          
            //拼接(注意这里序号为0的图片没有参与拼接),这里假定所有图片的相对偏移是一致的,这在流水线上非常常见。
            for (hv_Index = 1; hv_Index <14; hv_Index ++) //14
            {
             #region hv_Index = 1

if (hv_Index == 1) //第一幅图的情况
                {
                    ho_Image1.Dispose();
                    HOperatorSet.ReadImage(out ho_Image1, hv_ImageFiles.TupleSelect(hv_Index));
                    ho_Image2.Dispose();
                    HOperatorSet.ReadImage(out ho_Image2, hv_ImageFiles.TupleSelect(hv_Index + 1));
                    ho_Image11.Dispose();
                    HOperatorSet.ProjectiveTransImage(ho_Image1, out ho_Image11, hv_HomMat2D, "bilinear",
                        "false", "false");
                    ho_Image22.Dispose();
                    HOperatorSet.ProjectiveTransImage(ho_Image2, out ho_Image22, hv_HomMat2D, "bilinear",
                        "false", "false");

ho_Images1.Dispose();
                    HOperatorSet.GenEmptyObj(out ho_Images1);
                    ho_Images2.Dispose();
                    HOperatorSet.GenEmptyObj(out ho_Images2);
                    ho_Black.Dispose();
                    HOperatorSet.GenImageConst(out ho_Black, "byte", hv_Width, hv_Height);
                    OTemp[SP_O] = ho_Images1.CopyObj(1, -1);
                    SP_O++;
                    ho_Images1.Dispose();
                    HOperatorSet.ConcatObj(OTemp[SP_O - 1], ho_Image11, out ho_Images1);
                    OTemp[SP_O - 1].Dispose();
                    SP_O = 0;
                    OTemp[SP_O] = ho_Images1.CopyObj(1, -1);
                    SP_O++;
                    ho_Images1.Dispose();
                    HOperatorSet.ConcatObj(OTemp[SP_O - 1], ho_Image22, out ho_Images1);
                    OTemp[SP_O - 1].Dispose();
                    SP_O = 0;
                    ho_Imageresult0.Dispose();
                    //hv_Height+hv_Row1-hv_Row2为拼接后图片的长度
                    HOperatorSet.TileImagesOffset(ho_Images1, out ho_Imageresult0, (new HTuple(0)).TupleConcat(
                        hv_Row1 - hv_Row2), (new HTuple(0)).TupleConcat(0), (new HTuple(-1)).TupleConcat(
                        -1), (new HTuple(-1)).TupleConcat(-1), (new HTuple(-1)).TupleConcat(-1),
                        (new HTuple(-1)).TupleConcat(-1), hv_Width, hv_Height+hv_Row1-hv_Row2);

ho_Imageresult1.Dispose();
                    HOperatorSet.TileImagesOffset(ho_Image11, out ho_Imageresult1, 0, 0, -1, -1,
                        -1, -1, hv_Width, hv_Height + hv_Row1 - hv_Row2);
                    ho_Imageresult2.Dispose();
                    HOperatorSet.TileImagesOffset(ho_Image22, out ho_Imageresult2, hv_Row1 - hv_Row2,
                        0, -1, -1, -1, -1, hv_Width, hv_Height + hv_Row1 - hv_Row2);

//交界处融和,关键代码
                    HOperatorSet.GetImagePointer1(ho_Imageresult0, out hv_Pointer_tmp0, out hv_Type_tmp0, out hv_Width_tmp0, out hv_Height_tmp0);
                    HOperatorSet.GetImagePointer1(ho_Imageresult1, out hv_Pointer_tmp1, out hv_Type_tmp1, out hv_Width_tmp1, out hv_Height_tmp1);
                    HOperatorSet.GetImagePointer1(ho_Imageresult2, out hv_Pointer_tmp2, out hv_Type_tmp2, out hv_Width_tmp2, out hv_Height_tmp2);

long lWidth0 = (long)hv_Width_tmp0;  //现图
                    long lHeight0 = (long)hv_Height_tmp0;
                    long lWidth1 = (long)hv_Width_tmp1; //原图
                    long lHeight1 = (long)hv_Height_tmp1;
                    //         string sType = hv_Type_tmp.ToString();
                    Byte* IPByte0 = (Byte*)hv_Pointer_tmp0.I;
                    Byte* IPByte1 = (Byte*)hv_Pointer_tmp1.I;
                    Byte* IPByte2 = (Byte*)hv_Pointer_tmp2.I;
                    /*    long lrow = 0; long lcol = 0;*/
                    int irow1 = (int)hv_Row1.D; //row1
                    int irow2 = (int)hv_Row2.D;
                    int irow12 = Math.Abs(irow1 - irow2);

//读取到内存中
                    Byte[] G1 = new Byte[hv_Height_tmp1 * hv_Width_tmp1];
                    Byte[] G2 = new Byte[hv_Height_tmp1 * hv_Width_tmp1];
                    double a = 0; double b = 0;
                    for (int i = 0; i < lHeight1; i++)
                    {
                        for (int j = 0; j < lWidth1; j++)
                        {
                            G1[i * lWidth1 + j] = *IPByte1;
                            G2[i * lWidth1 + j] = *IPByte2;
                            IPByte1++;
                            IPByte2++;
                        }
                    }

//像素融和循环
                    for (int lcol = 0; lcol < lWidth0; lcol++)
                    {
                        for (int lrow = irow12; lrow < irow1; lrow++)
                        {

a = 1.0 * (irow1 - lrow) / irow2;
                            b = 1.0 * (lrow - irow12) / irow2;
                            IPByte0[lrow * lWidth0 + lcol] = (Byte)(G1[lrow * lWidth0 + lcol] * a + G2[lrow * lWidth0 + lcol] * b);
                        }

}
                    //把结果保存下来
                    HOperatorSet.CopyImage(ho_Imageresult0, out ho_ImageTmp);

#endregion
                }
                else   //不是第一幅图的情况
                {
                    ho_Image1.Dispose();
                    ho_Image11.Dispose();
                    HOperatorSet.CopyImage(ho_ImageTmp, out ho_Image1);
                    HOperatorSet.CopyImage(ho_ImageTmp, out ho_Image11);
                    ho_Image2.Dispose();
                    HOperatorSet.ReadImage(out ho_Image2, hv_ImageFiles.TupleSelect(hv_Index + 1));

//第二副图片需要镜头畸变
                    ho_Image22.Dispose();
                    HOperatorSet.ProjectiveTransImage(ho_Image2, out ho_Image22, hv_HomMat2D, "bilinear",
                        "false", "false");

//注意,这里ho_Images1变成图片组了,这个代码风格有问题
                    ho_Images1.Dispose();
                    HOperatorSet.GenEmptyObj(out ho_Images1);
                    ho_Images2.Dispose();
                    HOperatorSet.GenEmptyObj(out ho_Images2);

OTemp[SP_O] = ho_Images1.CopyObj(1, -1);
                    SP_O++;
                    ho_Images1.Dispose();
                    HOperatorSet.ConcatObj(OTemp[SP_O - 1], ho_Image11, out ho_Images1);
                    OTemp[SP_O - 1].Dispose();
                    SP_O = 0;
                    OTemp[SP_O] = ho_Images1.CopyObj(1, -1);
                    SP_O++;
                    ho_Images1.Dispose();
                    HOperatorSet.ConcatObj(OTemp[SP_O - 1], ho_Image22, out ho_Images1);
                    OTemp[SP_O - 1].Dispose();
                    SP_O = 0;
                    ho_Imageresult0.Dispose();
                    //hv_Height +(hv_Row1-hv_Row2)*hv_Index 是拼接后图片的长度
                    //(hv_Row1-hv_Row2)*hv_Index 是偏移长度
                    HOperatorSet.TileImagesOffset(ho_Images1, out ho_Imageresult0, (new HTuple(0)).TupleConcat(
                       (hv_Row1 - hv_Row2) * hv_Index), (new HTuple(0)).TupleConcat(0), (new HTuple(-1)).TupleConcat(
                        -1), (new HTuple(-1)).TupleConcat(-1), (new HTuple(-1)).TupleConcat(-1),
                        (new HTuple(-1)).TupleConcat(-1), hv_Width, hv_Height +(hv_Row1-hv_Row2)*hv_Index);

ho_Imageresult1.Dispose();
                     HOperatorSet.TileImagesOffset(ho_Image11, out ho_Imageresult1, 0, 0, -1, -1,
                         -1, -1, hv_Width, hv_Height + (hv_Row1 - hv_Row2) * hv_Index);
                     ho_Imageresult2.Dispose();
                     HOperatorSet.TileImagesOffset(ho_Image22, out ho_Imageresult2, (hv_Row1 - hv_Row2) * hv_Index,
                         0, -1, -1, -1, -1, hv_Width, hv_Height + (hv_Row1 - hv_Row2) * hv_Index);

//交界处融和,关键代码
                    HOperatorSet.GetImagePointer1(ho_Imageresult0, out hv_Pointer_tmp0, out hv_Type_tmp0, out hv_Width_tmp0, out hv_Height_tmp0);
                    HOperatorSet.GetImagePointer1(ho_Imageresult1, out hv_Pointer_tmp1, out hv_Type_tmp1, out hv_Width_tmp1, out hv_Height_tmp1);
                    HOperatorSet.GetImagePointer1(ho_Imageresult2, out hv_Pointer_tmp2, out hv_Type_tmp2, out hv_Width_tmp2, out hv_Height_tmp2);

long lWidth0 = (long)hv_Width_tmp0;  //现图
                    long lHeight0 = (long)hv_Height_tmp0;
                    long lWidth1 = (long)hv_Width_tmp1; //原图
                    long lHeight1 = (long)hv_Height_tmp1;
                    long lWidth2 = (long)hv_Width_tmp2; //原图
                    long lHeight2 = (long)hv_Height_tmp2;
                    //         string sType = hv_Type_tmp.ToString();
                    Byte* IPByte0 = (Byte*)hv_Pointer_tmp0.I;
                    Byte* IPByte1 = (Byte*)hv_Pointer_tmp1.I;
                    Byte* IPByte2 = (Byte*)hv_Pointer_tmp2.I;
                    /*    long lrow = 0; long lcol = 0;*/
                    int irow1 = (int)hv_Row1.D ; //row1
                    int irow2 = (int)hv_Row2.D ;
                    int irow12 = Math.Abs(irow1 - irow2);

//读取到内存中
                    Byte[] G1 = new Byte[hv_Height_tmp1 * hv_Width_tmp1];
                    Byte[] G2 = new Byte[hv_Height_tmp2 * hv_Width_tmp2];
                    double a = 0; double b = 0;
                    for (int i = 0; i < lHeight1; i++)
                    {
                        for (int j = 0; j < lWidth1; j++)
                        {
                             G1[i * lWidth1 + j] = *IPByte1;
                          
                            IPByte1++;
                        }
                    }
                    for (int i = 0; i < lHeight2; i++)
                    {
                        for (int j = 0; j < lWidth2; j++)
                        {
                            G2[i * lWidth2 + j] = *IPByte2;
                            IPByte2++;

}
                    }
                   IPByte1 = (Byte*)hv_Pointer_tmp1.I;
                   IPByte2 = (Byte*)hv_Pointer_tmp2.I;
                    int ioffset = irow12 * (hv_Index-1);

//像素融和循环
                    for (int lcol = 0; lcol < lWidth0; lcol++)
                    {
                        for (int lrow = irow12; lrow < irow1; lrow++)
                        {

a = 1.0 * (irow1 - lrow) / irow2;
                            b = 1.0 * (lrow - irow12) / irow2;
                            IPByte0[(lrow + ioffset) * lWidth0 + lcol] = (Byte)(G1[(lrow + ioffset) * lWidth0 + lcol] * a + G2[(lrow + ioffset) * lWidth0 + lcol] * b);

}
                    }
                    //把结果保存下来
                    HOperatorSet.CopyImage(ho_Imageresult0, out ho_ImageTmp);
                }

}

//成功输出结果
                HOperatorSet.WriteImage(ho_Imageresult0, "bmp", 0, outputname + "/" + "融合结果.bmp");

ho_ImageTemplete.Dispose();
            ho_Image1.Dispose();
            ho_Image2.Dispose();
            ho_Image11.Dispose();
            ho_Image22.Dispose();
            ho_ModelRegion.Dispose();
            ho__TmpRegion.Dispose();
            ho_TemplateImage.Dispose();
            ho_ModelContours.Dispose();
            ho_Images1.Dispose();
            ho_Images2.Dispose();
            ho_Black.Dispose();
            ho_Imageresult0.Dispose();
            ho_Imageresult2.Dispose();
            ho_Imageresult1.Dispose();
            return;

}
#endregion

}
}

结果运行界面

15张8秒。如果还有问题,请联系1755311380(QQ)

halcon+csharp多图像拼接实现的更多相关文章

  1. Halcon一日一练:图像拼接技术2:步骤与例程

    上一篇主要介绍了图像拼接的一些原理和方法,这一篇将主要介绍步骤和例程: 接上一篇: 基于特征的接拼方法,分为四个步骤 1.特征检测:从图像中检测出显著且独特的图像特征,诸如:闭合区域,直线段,边缘,轮 ...

  2. Halcon一日一练:图像拼接技术

    图像拼接技术就是针对同一场景的一系列图片,根据图片的特征,比如位置,重叠部分等,拼接成一张大幅的宽视角的图像. 图像拼接要求拼接后图像最大程度的与原图一致,失真尽可能的小,并且要尽量做到天衣无缝即没有 ...

  3. zw版·Halcon与delphi(兼谈opencv)

    zw版·Halcon与delphi(兼谈opencv) QQ群 247994767(delphi与halcon) <Halcon与delphi>系列,早两年就想写,不过一方面,因为Halc ...

  4. 《zw版·Halcon-delphi系列原创教程》 zw版-Halcon常用函数Top100中文速查手册

    <zw版·Halcon-delphi系列原创教程> zw版-Halcon常用函数Top100中文速查手册 Halcon函数库非常庞大,v11版有1900多个算子(函数). 这个Top版,对 ...

  5. zw版·全程图解Halcon控件安装(delphi2007版)

    zw版·全程图解Halcon控件安装(delphi2007版) delphi+halcon,这个组合,可以说是图像分析的神级配置,无论是开发效率,还是运行实在是太高了,分分钟秒杀c+opencv,py ...

  6. 《zw版·Halcon-delphi系列原创教程》 Halcon分类函数·简明中文手册 总览

    <zw版·Halcon-delphi系列原创教程> Halcon分类函数·简明中文手册 总览 Halcon函数库非常庞大,光HALCONXLib_TLB.pas文件,源码就要7w多行,但核 ...

  7. halcon,C# 学习

    Halcon学习之一:查询图像参数 1.get_grayval ( Image : : Row, Column : Grayval ) 计算Image图像中坐标为(Row,Column)的点的灰度值G ...

  8. halcon小结

    持更 应用范围 (罗列自官方帮助文档,以后有空了按照需求展开叙述) 1. 安全系统 2. 表面检测 3. 定位 4. 二维测量比较 5. 二维码识别 6. 二维位置定位 7. 二维物体识别 8. 光学 ...

  9. c#操作MangoDB 之MangoDB CSharp Driver驱动详解

    序言 MangoDB CSharp Driver是c#操作mongodb的官方驱动. 官方Api文档:http://api.mongodb.org/csharp/2.2/html/R_Project_ ...

随机推荐

  1. 如何提取cocos iOS应用程序APP与游戏安装包里的资源与文件

    平时玩手机,看到iOS app中许多不错的图片素材的时候,有木有很心动,是不是想把其中的图片资源导出来使用,即可以练手,又可以提高自己的审美观0-0,增加app的颜值.当然,请不要作为商业用途.开发软 ...

  2. selenium自定义find_element

    智能轮询元素是否显示: def isDisplayTimeOut(self,element,timeSes): """ 在指定时间内,轮询元素是否显示 :param el ...

  3. php实现记住密码下次自动登陆

    这篇博客里面还写到 实现“记住我的登录状态”的功能方法,简言之,就是对首先对session进行用户信息赋值,检测session,失效后,利用cookie对其赋值: 在实现过程中,根据网上一些代码贴,整 ...

  4. js区别手机和电脑打开网页

    Navigator对象 首先来了解一下Navigator 对象,Navigator 对象包含有关浏览器的信息,下面的userAgent 属性是一个只读的字符串,声明了浏览器用于 HTTP 请求的用户代 ...

  5. 数据库所有者 (dbo)

    数据库所有者 (dbo) dbo 是具有在数据库中执行所有活动的暗示性权限的用户.将固定服务器角色 sysadmin 的任何成员都映射到每个数据库内称为 dbo 的一个特殊用户上.另外,由固定服务器角 ...

  6. 认识ZTree

    ZTree基本知识 zTree 是一个依靠 jQuery 实现的多功能 “树插件”.优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. 一.最简单的树(标准的json数据): 1.set ...

  7. 决策树算法——ID3

    决策树算法是一种有监督的分类学习算法.利用经验数据建立最优分类树,再用分类树预测未知数据. 例子:利用学生上课与作业状态预测考试成绩. 上述例子包含两个可以观测的属性:上课是否认真,作业是否认真,并以 ...

  8. spriteJS

    https://blog.csdn.net/qq_37261367/article/details/84662028

  9. linux centos 如何设置swap大小?

    linux centos 如何设置swap大小? swap的值都是安装系统的时候设置好的,一般设置为内存的两倍大小.使用过程中发现swap值过小只能添加.用free -m 命令查看当前swap大小 使 ...

  10. 深入理解Node.js基于事件驱动的回调

    回调和异步调用的关系 首先明确一点,回调并非是异步调用,回调是一种解决异步函数执行结果的处理方法.在异步调用,如果我们希望将执行的结果返回并且处理时,可以通过回调的方法解决.为了能够更好的区分回调和异 ...