1.项目目的:1.halcon实现图像的MLP分类器 2.Qt作界面
2.项目环境:Qt5.14 halcon18 Win10
3.运行结果图
4.创建一个新的Qt项目
项目配置文件halcon_mlp.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
MLP.cpp \
main.cpp \
widget.cpp
HEADERS += \
MLP.h \
widget.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
win32:{
#halcon配置代码,已经将include、lib拷贝到项目之下
LIBS += -L$$PWD/halcon/win/lib/x64-win64/ -lhalcon
LIBS += -L$$PWD/halcon/win/lib/x64-win64/ -lhalconc
LIBS += -L$$PWD/halcon/win/lib/x64-win64/ -lhalconcpp
LIBS += -L$$PWD/halcon/win/lib/x64-win64/ -lhalconcppxl
LIBS += -L$$PWD/halcon/win/lib/x64-win64/ -lhalconcxl
LIBS += -L$$PWD/halcon/win/lib/x64-win64/ -lhalconxl
LIBS += -L$$PWD/halcon/win/lib/x64-win64/ -lhdevenginecpp
LIBS += -L$$PWD/halcon/win/lib/x64-win64/ -lhdevenginecppxl
LIBS += -L$$PWD/halcon/win/lib/x64-win64/ -llibiomp5md
#INCLUDEPATH += $$PWD/halcon/win/include
#DEPENDPATH += $$PWD/halcon/win/include
INCLUDEPATH += $$PWD/halcon/linux/include
DEPENDPATH += $$PWD/halcon/linux/include
}
unix:{
LIBS += -L$$PWD/halcon/linux/lib/x64-linux -lhalcon
LIBS += -L$$PWD/halcon/linux/lib/x64-linux -lhalconc
LIBS += -L$$PWD/halcon/linux/lib/x64-linux -lhalconcpp
LIBS += -L$$PWD/halcon/linux/lib/x64-linux -lhalconcppxl
LIBS += -L$$PWD/halcon/linux/lib/x64-linux/ -lhalconcxl
LIBS += -L$$PWD/halcon/linux/lib/x64-linux -lhalconxl
LIBS += -L$$PWD/halcon/linux/lib/x64-linux -lhdevenginecpp
LIBS += -L$$PWD/halcon/linux/lib/x64-linux -lhdevenginecppxl
INCLUDEPATH += $$PWD/halcon/linux/include
DEPENDPATH += $$PWD/halcon/linux/include
}
MLP.h
#ifndef MLP_H
#define MLP_H
#include "halconcpp/HalconCpp.h"
#include "Halcon.h"
using namespace HalconCpp;
class MLP
{
public:
static void gen_features (HObject ho_Image, HTuple *hv_FeatureVector);
static void gen_sobel_features (HObject ho_Image, HTuple hv_Features, HTuple *hv_FeaturesExtended);
};
#endif // MLP_H
MLP.cpp
#include "MLP.h"
void MLP::gen_sobel_features(HObject ho_Image, HTuple hv_Features, HTuple *hv_FeaturesExtended){
// Local iconic variables
HObject ho_EdgeAmplitude;
// Local control variables
HTuple hv_Energy, hv_Correlation, hv_Homogeneity;
HTuple hv_Contrast, hv_AbsoluteHistoEdgeAmplitude;
//Coocurrence matrix for 90 deg:
CoocFeatureImage(ho_Image, ho_Image, 6, 90, &hv_Energy, &hv_Correlation, &hv_Homogeneity,
&hv_Contrast);
//Absolute histogram of edge amplitudes:
SobelAmp(ho_Image, &ho_EdgeAmplitude, "sum_abs", 3);
GrayHistoAbs(ho_EdgeAmplitude, ho_EdgeAmplitude, 8, &hv_AbsoluteHistoEdgeAmplitude);
//
//You could of course compute more features:
//Entropy and anisotropy:
//entropy_gray (Image, Image, Entropy, Anisotropy)
//Absolute histogram of gray values:
//gray_histo_abs (Image, Image, 8, AbsoluteHistoImage)
//Add features to feature vector:
(*hv_FeaturesExtended).Clear();
(*hv_FeaturesExtended).Append(hv_Features);
(*hv_FeaturesExtended).Append(hv_Energy);
(*hv_FeaturesExtended).Append(hv_Correlation);
(*hv_FeaturesExtended).Append(hv_Homogeneity);
(*hv_FeaturesExtended).Append(hv_Contrast);
(*hv_FeaturesExtended) = (*hv_FeaturesExtended).TupleConcat(hv_AbsoluteHistoEdgeAmplitude);
//Activate the following lines to add the additional features you activated:
//FeaturesExtended := [FeaturesExtended,Entropy,Anisotropy]
//FeaturesExtended := [FeaturesExtended,AbsoluteHistoImage]
return;
}
void MLP::gen_features(HObject ho_Image, HTuple *hv_FeatureVector){
// Local iconic variables
HObject ho_Zoomed1;
(*hv_FeatureVector) = HTuple();
//Compute features.
gen_sobel_features(ho_Image, (*hv_FeatureVector), &(*hv_FeatureVector));
//Downscale the image (image pyramid) and compute features.
ZoomImageFactor(ho_Image, &ho_Zoomed1, 0.5, 0.5, "constant");
gen_sobel_features(ho_Zoomed1, (*hv_FeatureVector), &(*hv_FeatureVector));
//Uncomment lines to use further pyramid levels:
//zoom_image_factor (Zoomed1, Zoomed2, 0.5, 0.5, 'constant')
//gen_sobel_features (Zoomed2, FeatureVector, FeatureVector)
//zoom_image_factor (Zoomed2, Zoomed3, 0.5, 0.5, 'constant')
//gen_sobel_features (Zoomed3, FeatureVector, FeatureVector)
//zoom_image_factor (Zoomed3, Zoomed4, 0.5, 0.5, 'constant')
//gen_sobel_features (Zoomed4, FeatureVector, FeatureVector)
(*hv_FeatureVector) = (*hv_FeatureVector).TupleReal();
return;
}
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QStyle>
#include <QFileDialog>
#include <QDebug>
#include <QTabWidget>
#include <QTableWidget>
#include <QHeaderView>
#include <QTableWidgetItem>
#include <QSpinBox>
#include <QMessageBox>
#include <QTimer>
#include <QMouseEvent>
#include <QLineEdit>
#include "halconcpp/HalconCpp.h"
#include "Halcon.h"
using namespace HalconCpp;
#pragma execution_character_set("utf-8") //支持中文
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
void createWidget();
QTimer *timer;
QLabel *label_ImageShow;
QPushButton *btn_OpenImage;
QPushButton *btn_OpenCamera;
QPushButton *btn_CloseCamera;
HTuple hv_WindowHandle;
HTuple hv_AcqHandle;
HObject ho_Image;
HTuple hv_Width, hv_Height;
Hlong MainWndID;
QPushButton *btn_ROI;
bool DrawROI;
QSpinBox *spinBox_classNo;
QSpinBox *spinBox_classNum;
QPushButton *btn_classNum;
QPushButton *btn_AddImg;
QPushButton *btn_TrainMLP;
QPushButton *btn_Classify;
QTableWidget *tableWidget;
QPoint SPoint;
QPoint EPoint;
QPoint sPoint;
QPoint ePoint;
HObject ROIContour;
HTuple hv_rows, hv_cols;
HObject ho_ImageReduced;
HObject ho_Rectangle;
HObject ho_Images;
HTuple hv_Index;
HTuple hv_MLPHandle;
HTuple hv_NumClasses;
bool isClassify;//是否识别
void Classify();
private slots:
void on_btn_OpenImage_clicked();
void on_btn_OpenCamera_clicked();
void on_btn_CloseCamera_clicked();
void camera();
void on_btn_ROI_clicked();
void on_btn_AddImg_clicked();
void on_btn_classNum_clicked();
void on_btn_TrainMLP_clicked();
void on_btn_Classify_clicked();
protected:
void mousePressEvent(QMouseEvent * e);
void mouseMoveEvent(QMouseEvent * e);
void mouseReleaseEvent(QMouseEvent * e);
};
#endif // WIDGET_H
Widget.cpp
#include "widget.h"
#include "MLP.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
createWidget();
timer = new QTimer(this);
DrawROI = false;
GenEmptyObj(&ho_Images);
hv_Index = HTuple();
isClassify = false;
connect(btn_OpenImage,SIGNAL(clicked()),this,SLOT(on_btn_OpenImage_clicked()));
connect(btn_OpenCamera,SIGNAL(clicked()),this,SLOT(on_btn_OpenCamera_clicked()));
connect(btn_CloseCamera,SIGNAL(clicked()),this,SLOT(on_btn_CloseCamera_clicked()));
connect(timer,SIGNAL(timeout()),this,SLOT(camera()));
connect(btn_ROI,SIGNAL(clicked()),this,SLOT(on_btn_ROI_clicked()));
connect(btn_AddImg,SIGNAL(clicked()),this,SLOT(on_btn_AddImg_clicked()));
connect(btn_classNum,SIGNAL(clicked()),this,SLOT(on_btn_classNum_clicked()));
connect(btn_Classify,SIGNAL(clicked()),this,SLOT(on_btn_Classify_clicked()));
connect(btn_TrainMLP,SIGNAL(clicked()),this,SLOT(on_btn_TrainMLP_clicked()));
}
Widget::~Widget()
{
}
void Widget::createWidget()
{
this->setFixedSize(916,547);
btn_OpenImage = new QPushButton(this);
btn_OpenImage->setGeometry(350,495,100,40);
btn_OpenImage->setText("打开图片");
btn_OpenCamera = new QPushButton(this);
btn_OpenCamera->setGeometry(630,495,100,40);
btn_OpenCamera->setText("打开相机");
btn_CloseCamera = new QPushButton(this);
btn_CloseCamera->setGeometry(780,495,100,40);
btn_CloseCamera->setText("关闭相机");
btn_OpenCamera->setEnabled(true);
btn_CloseCamera->setEnabled(false);
label_ImageShow =new QLabel(this);
label_ImageShow->setGeometry(290,20,611,461);
MainWndID = (Hlong)this->label_ImageShow->winId();
SetWindowAttr("background_color","gray");//设置背景为灰色
OpenWindow(0, 0, label_ImageShow->width(), label_ImageShow->height(), MainWndID,
"visible", "", &hv_WindowHandle);
HDevWindowStack::Push(hv_WindowHandle);
QTabWidget *tabwidget = new QTabWidget(this);
QWidget *tab0 = new QWidget;
QWidget *tab1 = new QWidget;
tabwidget->addTab(tab0, "参数0");
tabwidget->addTab(tab1, "参数1");
tabwidget->setGeometry(20, 20, 250, 462);
tabwidget->setTabShape(QTabWidget::Triangular);
btn_ROI = new QPushButton(tab0);
btn_ROI->setGeometry(70,20,100,30);
btn_ROI->setText("设置ROI");
QLabel *label0 = new QLabel(tab0);
label0->setGeometry(20,70,80,30);
label0->setText("种类数:");
label0->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
spinBox_classNum = new QSpinBox(tab0);
spinBox_classNum->setRange(1,99);
spinBox_classNum->setValue(1);
spinBox_classNum->setGeometry(100,70,50,30);
btn_classNum =new QPushButton(tab0);
btn_classNum->setGeometry(160,70,50,30);
btn_classNum->setText("确认");
QLabel *label1 = new QLabel(tab0);
label1->setGeometry(20,120,80,30);
label1->setText("类别编号:");
label1->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
spinBox_classNo = new QSpinBox(tab0);
//spinBox_classNo->setRange(0,99);
spinBox_classNo->setValue(0);
spinBox_classNo->setGeometry(100,120,50,30);
//禁用,待种类数确认后改可用
spinBox_classNo->setEnabled(false);
btn_AddImg =new QPushButton(tab0);
btn_AddImg->setGeometry(160,120,50,30);
btn_AddImg->setText("添加");
//禁用,待种类数确认后改可用
btn_AddImg->setEnabled(false);
btn_TrainMLP = new QPushButton(tab0);
btn_TrainMLP->setGeometry(50,170,150,30);
btn_TrainMLP->setText("训练神经网络");
btn_Classify = new QPushButton(tab0);
btn_Classify->setGeometry(50,220,150,30);
btn_Classify->setText("识别图像");
tableWidget = new QTableWidget(tab0);
tableWidget->setRowCount(0);
tableWidget->setColumnCount(3);
//page2->addWidget();
tableWidget->setGeometry(0,250,244,187);
tableWidget->verticalHeader()->setVisible(false); //隐藏列表头
//tableWidget->horizontalHeader()->setVisible(false); //隐藏行表头
//tableWidget->setSelectionBehavior ( QAbstractItemView::SelectRows); //设置选择行为,以行为单位
//tableWidget->setSelectionMode ( QAbstractItemView::SingleSelection); //设置选择模式,选择单行
tableWidget->horizontalHeader()->setSectionResizeMode(0,QHeaderView::ResizeToContents);
//tableWidget->horizontalHeader()->setSectionResizeMode(1,QHeaderView::ResizeToContents);
tableWidget->setColumnWidth(1, 70);
tableWidget->horizontalHeader()->setSectionResizeMode(2,QHeaderView::Stretch);
//tableWidget->show();
QStringList headerText;
headerText<<"类别编号"<<"类别"<<"数量";
tableWidget->setHorizontalHeaderLabels(headerText);
//tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
tableWidget->horizontalHeader()->setDisabled(true);//禁止用户拖动改变列宽
tableWidget->verticalHeader()->setDisabled(true);//设置行不能拖动
}
void Widget::on_btn_OpenImage_clicked(){
qDebug() << "读取图片";
ClearWindow(hv_WindowHandle);
QString file_name = QFileDialog::getOpenFileName(this,tr("open file"),"."
,tr("Video Files(*.bmp *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm *.jpeg)"));
try
{
ReadImage(&ho_Image,file_name.toLatin1().data());
GetImageSize(ho_Image, &hv_Width, &hv_Height);
SetPart(hv_WindowHandle, 0, 0, hv_Height, hv_Width);
if (HDevWindowStack::IsOpen())
{
ClearWindow(HDevWindowStack::GetActive());
DispObj(ho_Image, HDevWindowStack::GetActive());
}
}
catch (HException &HDevExpDefaultException)
{
HTuple hv_Exception;
HDevExpDefaultException.ToHTuple(&hv_Exception);
//qDebug() << "0";
}
}
void Widget::on_btn_OpenCamera_clicked(){
qDebug() << "打开相机";
//qle->setText("打开相机");
ClearWindow(hv_WindowHandle);
timer->start(20);//定时器开始工作,参数影响帧率
try
{
OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false",
"default", "[0]", 0, -1, &hv_AcqHandle);//只会打开序号0的相机,修改"[0]",改变连接上的相机
GrabImageStart(hv_AcqHandle, -1);
//在openwindow前先抓取一帧图片
GrabImage(&ho_Image, hv_AcqHandle);
GetImageSize(ho_Image, &hv_Width, &hv_Height);
btn_CloseCamera->setEnabled(true);
btn_OpenCamera->setEnabled(false);
btn_OpenImage->setEnabled(false);
}
catch (HException &HDevExpDefaultException)
{
HTuple hv_Exception;
HDevExpDefaultException.ToHTuple(&hv_Exception);
}
}
void Widget::on_btn_CloseCamera_clicked(){
qDebug() << "关闭相机";
//qle->setText("关闭相机");
timer->stop();
CloseFramegrabber(hv_AcqHandle);
ClearWindow(hv_WindowHandle);
btn_CloseCamera->setEnabled(false);
btn_OpenCamera->setEnabled(true);
btn_OpenImage->setEnabled(true);
}
void Widget::camera()
{
try {
GrabImage(&ho_Image, hv_AcqHandle);
GetImageSize(ho_Image, &hv_Width, &hv_Height);
SetPart(hv_WindowHandle, 0, 0, hv_Height, hv_Width);
if(HDevWindowStack::IsOpen())
{
ClearWindow(HDevWindowStack::GetActive());
DispObj(ho_Image,HDevWindowStack::GetActive());
}
if(DrawROI){
//ClearWindow(hv_WindowHandle);
SetColor(HDevWindowStack::GetActive(),"green");
SetLineWidth(HDevWindowStack::GetActive(),4);
DispObj(ROIContour,HDevWindowStack::GetActive());
GenRectangle1(&ho_Rectangle, sPoint.y(), sPoint.x(), ePoint.y(), ePoint.x());
//对ROI区域进行裁剪
ReduceDomain(ho_Image, ho_Rectangle, &ho_ImageReduced);
//qDebug()<<"成功截取感兴趣区域";
//
if(isClassify){
Classify();
}
}
}
catch (HException &HDevExpDefaultException)
{
HTuple hv_Exception;
HDevExpDefaultException.ToHTuple(&hv_Exception);
}
}
void Widget::on_btn_ROI_clicked()
{
DrawROI = !DrawROI;
qDebug() << "DrawROI"<<QString::number(DrawROI);
ClearWindow(HDevWindowStack::GetActive());
if(DrawROI){
btn_ROI->setText("取消ROI");
try
{
if (HDevWindowStack::IsOpen()){
SetColor(HDevWindowStack::GetActive(),"green");
SetLineWidth(HDevWindowStack::GetActive(),4);
DispObj(ho_Image, HDevWindowStack::GetActive());
DispObj(ROIContour,HDevWindowStack::GetActive());
GenRectangle1(&ho_Rectangle, sPoint.y(), sPoint.x(), ePoint.y(), ePoint.x());
//对ROI区域进行裁剪
ReduceDomain(ho_Image, ho_Rectangle, &ho_ImageReduced);
qDebug()<<"成功截取感兴趣区域";
}
}catch (HException &HDevExpDefaultException)
{
HTuple hv_Exception;
HDevExpDefaultException.ToHTuple(&hv_Exception);
qDebug() <<"错误";
}
}
else{
btn_ROI->setText("设置ROI");
try {
if (HDevWindowStack::IsOpen()){
DispObj(ho_Image, HDevWindowStack::GetActive());
}
} catch (HException &HDevExpDefaultException)
{
HTuple hv_Exception;
HDevExpDefaultException.ToHTuple(&hv_Exception);
qDebug() <<"错误";
}
}
}
//鼠标 点击
void Widget::mousePressEvent(QMouseEvent *e)
{
//获取点击的下标
if(DrawROI){
if(label_ImageShow->geometry().contains(this->mapFromGlobal(QCursor::pos())) //鼠标是否在界面上
&&e->button()==Qt::LeftButton)
{
qDebug() << "左键" ;
SPoint.setX(e->x());
SPoint.setY(e->y());
qDebug() <<"SX:"<< SPoint.x();
qDebug() <<"SY:"<< SPoint.y();
}
}
}
//鼠标 移动
void Widget::mouseMoveEvent(QMouseEvent * e)
{
if(DrawROI){
if(label_ImageShow->geometry().contains(this->mapFromGlobal(QCursor::pos())))//鼠标是否在界面上
{
qDebug() << "左键位置移动到" ;
EPoint.setX(e->x());
EPoint.setY(e->y());
qDebug() <<"EX:"<< SPoint.x();
qDebug() <<"EY:"<< SPoint.y();
}
double scale_x;
double scale_y;
try
{
GetImageSize(ho_Image, &hv_Width, &hv_Height);
scale_x = (double)hv_Width / label_ImageShow->width();
scale_y = (double)hv_Height / label_ImageShow->height();
sPoint.setX((SPoint.x()-label_ImageShow->geometry().x())*scale_x);
sPoint.setY((SPoint.y()-label_ImageShow->geometry().y())*scale_y);
qDebug() <<"sX:"<< sPoint.x();
qDebug() <<"sY:"<< sPoint.y();
ePoint.setX((EPoint.x()-label_ImageShow->geometry().x())*scale_x);
ePoint.setY((EPoint.y()-label_ImageShow->geometry().y())*scale_y);
qDebug() <<"eX:"<< ePoint.x();
qDebug() <<"eY:"<< ePoint.y();
//HObject ROIContour;
//HTuple hv_rows, hv_cols;
hv_rows.Clear();
hv_rows[0] = sPoint.y();
hv_rows[1] = ePoint.y();
hv_rows[2] = ePoint.y();
hv_rows[3] = sPoint.y();
hv_rows[4] = sPoint.y();
hv_cols.Clear();
hv_cols[0] = sPoint.x();
hv_cols[1] = sPoint.x();
hv_cols[2] = ePoint.x();
hv_cols[3] = ePoint.x();
hv_cols[4] = sPoint.x();
GenContourPolygonXld(&ROIContour, hv_rows, hv_cols);
ClearWindow(HDevWindowStack::GetActive());
SetColor(HDevWindowStack::GetActive(),"green");
SetLineWidth(HDevWindowStack::GetActive(),4);
DispObj(ho_Image, HDevWindowStack::GetActive());
DispObj(ROIContour,HDevWindowStack::GetActive());
}
catch (HException &HDevExpDefaultException)
{
HTuple hv_Exception;
HDevExpDefaultException.ToHTuple(&hv_Exception);
qDebug() <<"错误";
}
}
}
//鼠标 松开
void Widget::mouseReleaseEvent(QMouseEvent * e)
{
if(DrawROI){
try{
GenRectangle1(&ho_Rectangle, sPoint.y(), sPoint.x(), ePoint.y(), ePoint.x());
//对ROI区域进行裁剪
ReduceDomain(ho_Image, ho_Rectangle, &ho_ImageReduced);
qDebug()<<"成功截取感兴趣区域";
}
catch (HException &HDevExpDefaultException)
{
HTuple hv_Exception;
HDevExpDefaultException.ToHTuple(&hv_Exception);
//qle_result->setText("创建模板失败");
//DispObj(ho_Image, HDevWindowStack::GetActive());
}
}
}
void Widget::on_btn_AddImg_clicked(){
qDebug()<<"添加训练图像";
/*
QTableWidgetItem *item0 = new QTableWidgetItem(QString::number(hv_Number.I()-1));
item0->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//内容居中
tableWidget->setItem(hv_Number.I()-1, 0, item0);
QTableWidgetItem *item1 = new QTableWidgetItem(QString(detectionResult));
item1->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//内容居中
*/
//将当前截取图像添加进图像集合
//建立索引,即每张图像的种类编号的组合
/*
index :=[]
classNo := 0
tuple_insert (index, |index|, classNo, index)
classNo := 1
tuple_insert (index, |index|, classNo, index)
classNo := 2
tuple_insert (index, |index|, classNo, index)
classNo := 1
tuple_insert (index, |index|, classNo, index)
classNo := 2
tuple_insert (index, |index|, classNo, index)
classNo := 2
tuple_insert (index, |index|, classNo, index)
tuple_find (index, 0, Indices0)
tuple_find (index, 1, Indices1)
tuple_find (index, 2, Indices2)
*/
TupleInsert(hv_Index, hv_Index.TupleLength(), spinBox_classNo->value(), &hv_Index);
qDebug()<<"hv_Index个数"<<hv_Index.TupleLength().I();
//将roi截图添加入hv_images集合中
ConcatObj(ho_Images, ho_ImageReduced, &ho_Images);
HTuple hv_Number;
CountObj(ho_Images, &hv_Number);
qDebug()<<"ho_Images个数"<<hv_Number.I();
//qDebug()<<"hv_Index:"<<hv_Index.I();
/*
for(int i =0;i<hv_Index.TupleLength().I();i++){
//hv_a = ((const HTuple&)hv_Indices1)[1];
qDebug()<<"hv_Index:"<<(((const HTuple&)hv_Index)[i]).I();
}
*/
//确认每个种类的个数
for(int i = 0; i<spinBox_classNum->value(); i++){
HTuple hv_Indices;
TupleFind(hv_Index, i, &hv_Indices);
//qDebug()<<"数值"+QString::number(i)+"个数:"<<hv_Indices.TupleLength().I();有问题,如果没有找到会赋值-1,个数会变成1
/*
QTableWidgetItem *item2 = new QTableWidgetItem(QString::number(hv_Indices.TupleLength().I()));
item2->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//内容居中
tableWidget->setItem(i, 2, item2);
*/
if (0 != (int(hv_Indices==-1)))//hv_Indices<0或hv_Indices==-1
{
qDebug()<<"数值"+QString::number(i)+"个数:0";
QTableWidgetItem *item2 = new QTableWidgetItem(QString::number(0));
item2->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//内容居中
tableWidget->setItem(i, 2, item2);
}
else{
qDebug()<<"数值"+QString::number(i)+"个数:"+QString::number(hv_Indices.TupleLength().I());
QTableWidgetItem *item2 = new QTableWidgetItem(QString::number(hv_Indices.TupleLength().I()));
item2->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//内容居中
tableWidget->setItem(i, 2, item2);
}
}
}
void Widget::on_btn_classNum_clicked(){
qDebug()<<"确认图像种类数";
spinBox_classNo->setEnabled(true);
btn_AddImg->setEnabled(true);
spinBox_classNo->setRange(0,spinBox_classNum->value()-1);
tableWidget->setRowCount(spinBox_classNum->value());
//添加表格的数据,添加前先清除数据
tableWidget->clearContents();
for(int i = 0; i<spinBox_classNum->value(); i++){
QTableWidgetItem *item0 = new QTableWidgetItem(QString::number(i));
item0->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//内容居中
item0->setFlags(item0->flags() & (~Qt::ItemIsEditable)); //可选中,但是不可编辑
tableWidget->setItem(i, 0, item0);
QTableWidgetItem *item1 = new QTableWidgetItem();
//table_item.setItem(row, column, QTableWidgetItem(str(value)))
//item1->setFixedWidth(50);
//item1->setFlags(Qt::ItemIsEditable);
tableWidget->setItem(i,1,item1);
QTableWidgetItem *item2 = new QTableWidgetItem(QString::number(0));
item2->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//内容居中
item0->setFlags(item2->flags() & (~Qt::ItemIsEditable)); //可选中,但是不可编辑
tableWidget->setItem(i, 2, item2);
}
}
void Widget::on_btn_Classify_clicked(){
qDebug()<<"识别图像";
//qDebug()<<tableWidget->item(0,1)->text();
isClassify = !isClassify;//取反
}
void Widget::on_btn_TrainMLP_clicked(){
qDebug()<<"训练网络";
//训练前先清除mlp
ClearClassMlp(hv_MLPHandle);
//HTuple hv_FeatureVector;
//MLP::gen_features(ho_ImageReduced, &hv_FeatureVector);
//MLP::gen_features(ho_ImageReduced, &hv_FeatureVector);
HTuple hv_Number;
CountObj(ho_Images, &hv_Number);
HTuple hv_FeatureVector;
for (int i=1;i<=hv_Number;i++) {
MLP::gen_features(ho_Images[i], &hv_FeatureVector);
qDebug()<<"图像特征长度:"+QString::number(hv_FeatureVector.TupleLength().I());
//果然都是72长度
}
HTuple hv_NumFeatures;
hv_NumFeatures = hv_FeatureVector.TupleLength();
HTuple hv_classes;
for (int i =0; i <tableWidget->rowCount();i++) {
TupleInsert(hv_classes, hv_classes.TupleLength(), i, &hv_classes);
}
//HTuple hv_NumClasses;
hv_NumClasses = hv_classes.TupleLength();
HTuple hv_NumHidden;
hv_NumHidden = 15;
CreateClassMlp(hv_NumFeatures, hv_NumHidden, hv_NumClasses, "softmax", "normalization",
10, 42, &hv_MLPHandle);
//给不同Classes的截取添加到MLP中
for (int i = 0;i <hv_NumClasses;i++) {
int currentclass;
currentclass = hv_classes[i];//其实和i值相同
HTuple hv_Indices;
hv_Indices = HTuple();
TupleFind(hv_Index, currentclass, &hv_Indices);//获得图像种类的索引标号
//首先判断hv_Indices是否为-1
if (0 != (int(hv_Indices==-1)))//hv_Indices<0或hv_Indices==-1
{
//什么也事务也不处理
qDebug()<<"种类"+QString::number(currentclass)+"个数为0";
}
else{
qDebug()<<"种类"+QString::number(currentclass)+"个数为"+QString::number(hv_Indices.TupleLength().I());
//执行添加操作
for (int j =0;j<hv_Indices.TupleLength().I();j++) {
HTuple currentindex;
currentindex = hv_Indices[j];
//qDebug()<<"1";
//ho_Images[currentindex];
qDebug()<<QString::number(currentindex.I());
MLP::gen_features(ho_Images[currentindex.I()+1], &hv_FeatureVector);
//qDebug()<<"2";
AddSampleClassMlp(hv_MLPHandle, hv_FeatureVector,HTuple(currentclass));
//qDebug()<<"3";
}
}
}
//训练MLP
HTuple hv_Error, hv_ErrorLog;
TrainClassMlp(hv_MLPHandle, 200, 1, 0.01, &hv_Error, &hv_ErrorLog);
qDebug()<<"训练完成";
}
void Widget::Classify(){
HTuple hv_FeatureVector_test;
MLP::gen_features(ho_ImageReduced, &hv_FeatureVector_test);
HTuple hv_FoundClassIDs, hv_Confidence;
ClassifyClassMlp(hv_MLPHandle, hv_FeatureVector_test, hv_NumClasses, &hv_FoundClassIDs, &hv_Confidence);
//显示识别结果
try {
SetColor(HDevWindowStack::GetActive(),"blue");
SetLineWidth(HDevWindowStack::GetActive(),6);
HTuple hv_Font, hv_FontWithSize;
QueryFont(HDevWindowStack::GetActive(), &hv_Font);
hv_FontWithSize = HTuple(hv_Font[0])+"-20";
SetFont(HDevWindowStack::GetActive(), hv_FontWithSize);
//SetFont(HDevWindowStack::GetActive(), HTuple("黑体-20"));
//SetFont("黑体-20");
SetTposition(HDevWindowStack::GetActive(), 20, 20);
WriteString(HDevWindowStack::GetActive(), "种类编号:"+hv_FoundClassIDs[0]);
SetTposition(HDevWindowStack::GetActive(), 40, 20);
//qDebug()<<tableWidget->item(0,1)->text();
QString str = tableWidget->item(hv_FoundClassIDs[0].I(),1)->text();
//qDebug()<<str;
//str = "类别:"+str;
//WriteString(HDevWindowStack::GetActive(), str.toLatin1().data());
WriteString(HDevWindowStack::GetActive(), "类别:");
SetTposition(HDevWindowStack::GetActive(), 40, 100);
WriteString(HDevWindowStack::GetActive(), str.toLatin1().data());
SetTposition(HDevWindowStack::GetActive(), 60, 20);
WriteString(HDevWindowStack::GetActive(), "确信值:"+hv_Confidence[0]);
}catch (HException &HDevExpDefaultException)
{
HTuple hv_Exception;
HDevExpDefaultException.ToHTuple(&hv_Exception);
}
}
//
/
/
附录halcon杂代码
index :=[]
classNo := 0
tuple_insert (index, |index|, classNo, index)
classNo := 1
tuple_insert (index, |index|, classNo, index)
classNo := 2
tuple_insert (index, |index|, classNo, index)
classNo := 1
tuple_insert (index, |index|, classNo, index)
classNo := 2
tuple_insert (index, |index|, classNo, index)
classNo := 2
tuple_insert (index, |index|, classNo, index)
tuple_find (index, 0, Indices0)
tuple_find (index, 1, Indices1)
tuple_find (index, 2, Indices2)
create_class_mlp (72, 16, 2, 'softmax', \
'normalization', 1, 42, MLPHandle)
train_class_mlp (MLPHandle, 100, 1, 0.01, Error, ErrorLog)
write_class_mlp (MLPHandle, 'classifier.mlp')
read_samples_class_mlp (MLPHandle, 'samples.mtf')
*将MLP模型写入文件
write_class_mlp (MLPHandle, 'classifier.mlp')
*从文件中读入一个MLP模型
read_class_mlp ('classifier.mlp', MLPHandle1)
*清除MLP
clear_class_mlp (MLPHandle1)