图像校正场景一般有两种,其一由镜头本身或安装角度引起,其二是被拍摄物品本身引起
理论处理流程
我的处理处理流程
1,加载网格校正图像
2,确定符合条件的网格区域
3,显示网格鞍点
4,显示网格线
5,确定最终需要扭曲校正的图像
6,显示校正后图像
7,加载需要校正的图像
8,显示校正后图像效果
显而易见,校正后的图像在字符识别,缺陷检测,尺寸测量等方面检测效果要优于原图。
附上源码
(注意,源码仅供流程参考,在实战项目过程中,方法最好封装成类亦或者Dll文件,参数可以适当开放方便后期调试,映射关系需保存本地,软件重启需重新读取参数)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ViewControl;
using HalconDotNet;
using System.Reflection.Emit;
using static System.Net.Mime.MediaTypeNames;
namespace DeepLearningTest1
{
public partial class Form1 : Form
{
HalconView HW;
HObject HIMage = new HObject(), ho_ImageReduced=new HObject(),ho_ConnectingLines=new HObject(), ho_Map=new HObject();
HObject ho_ImageMapped =new HObject();
HObject ho_GridRegion;
HTuple hv_Row = new HTuple(), hv_Col = new HTuple();
public Form1()
{
InitializeComponent();
HW = new HalconView();
HW.HWindowControl.BackColor = Color.White;
splitContainer1.Panel2.Controls.Add(HW);
HW.Dock = DockStyle.Fill;
}
private void button1_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog openFileDialog = new OpenFileDialog();
//openFileDialog.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
openFileDialog.Filter = "图片文件(*.bmp;*.jpg;*.gif;*.png;*.tiff;*.tif)|*.bmp;*.jpg;*.gif;*.png;*.tiff;*.tif";
openFileDialog.RestoreDirectory = true;
openFileDialog.FilterIndex = 1;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
label3.Text = openFileDialog.FileName;
HOperatorSet.ReadImage(out HIMage, label3.Text);
HW.DispImage(HIMage, true);
}
}
catch (Exception ex)
{
MessageBox.Show("加载图片失败 " + ex.ToString());
}
}
/// <summary>
/// 1 确定整流网格区域
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
if (!HIMage.IsInitialized()) { MessageBox.Show("图片为空"); return; }
HOperatorSet.GenEmptyObj(out ho_GridRegion);
ho_GridRegion.Dispose();
HOperatorSet.FindRectificationGrid(HIMage, out ho_GridRegion, 25,10);
ho_ImageReduced.Dispose();
HOperatorSet.ReduceDomain(HIMage, ho_GridRegion, out ho_ImageReduced);
HW.DispObject(ho_GridRegion);
}
/// <summary>
///2 确定网格点。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
//---------------------2-----------------------------
//确定网格点。
HTuple hv_Threshold = new HTuple();
HObject ho_SaddlePoints;
HOperatorSet.GenEmptyObj(out ho_SaddlePoints);
hv_Row.Dispose(); hv_Col.Dispose();
HOperatorSet.SaddlePointsSubPix(ho_ImageReduced, "facet", 1.5,
5, out hv_Row, out hv_Col);
ho_SaddlePoints.Dispose();
HOperatorSet.GenCrossContourXld(out ho_SaddlePoints, hv_Row, hv_Col, 6, 0.785398);
HOperatorSet.SetColor(HW.HalconWindow, "red");
HW.DispObject(HIMage);
HW.DispObject(ho_SaddlePoints);
}
/// <summary>
/// 网格线区域
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button4_Click(object sender, EventArgs e)
{
HTuple hv_SigmaConnectGridPoints = new HTuple();
HTuple hv_MaxDist = new HTuple();
//------------------------3------------------------
//确定网格线。
ho_ConnectingLines.Dispose();
HOperatorSet.ConnectGridPoints(ho_ImageReduced, out ho_ConnectingLines, hv_Row, hv_Col, 0.9, 5.0);
HW.DispObject(HIMage);
HW.DispObject(ho_ConnectingLines);
}
/// <summary>
/// 输出映射关系
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button5_Click(object sender, EventArgs e)
{
HObject ho_Meshes;
HOperatorSet.GenEmptyObj(out ho_Meshes);
HTuple hv_GridSpacing = new HTuple();
ho_Map.Dispose(); ho_Meshes.Dispose();
HOperatorSet.GenGridRectificationMap(ho_ImageReduced, 20, out ho_Map,
out ho_Meshes, hv_GridSpacing, 0, hv_Row, hv_Col, "bilinear");
HW.DispObject(HIMage);
HW.DispObject(ho_Meshes);
}
/// <summary>
/// 映射原图像
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button6_Click(object sender, EventArgs e)
{
ho_ImageMapped.Dispose();
HOperatorSet.MapImage(ho_ImageReduced, ho_Map, out ho_ImageMapped);
HW.DispObject(ho_ImageMapped);
}
/// <summary>
/// 加载其他图像映射
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button7_Click(object sender, EventArgs e)
{
ho_ImageReduced.Dispose();
HOperatorSet.ReduceDomain(HIMage, ho_GridRegion, out ho_ImageReduced);
ho_ImageMapped.Dispose();
HOperatorSet.MapImage(ho_ImageReduced, ho_Map, out ho_ImageMapped);
HW.DispObject(ho_ImageMapped);
}
}
}