生丝疵点检测上位机

目录

实验总结

代码

图像处理部分

SVM分类部分

类函数部分

主函数部分

效果

链接


实验总结

代码大致分为两部分,建了两个UI窗口,一部分是图像处理并分割出疵点图像,第二部分使用SVM(之前做的)进行分类,在第一个UI中调用第二个UI。

代码

图像处理部分

.h

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_imgProcess.h"
#include <QLabel>
#include <QString>
#include <QFileDialog>
#include <QDir>
#include <QFile>
#include <QDebug>
#include <QImage>


class imgProcess : public QMainWindow
{
    Q_OBJECT

private:

    void initUI();

public:
    imgProcess(QWidget *parent = Q_NULLPTR);

public slots:
    void openImg();
    void processImg();
    void SVMDetect();


private:
    Ui::imgProcessClass ui;
};

.cpp

#include "imgProcess.h"
#include<iostream>
#include<opencv2/opencv.hpp>
#include "img.h" //用于图像处理的类
#include "Widget.h"



using namespace cv;
using namespace std;


Mat cvimg; //用于QTImage 转换到 CVImage 进行图像处理
img imgP; // 进行类的声明

Mat QCTransfer(QImage image) 
{
    Mat dst;
    dst = Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
    return dst;
}
void imgProcess::initUI()
{
   


}

imgProcess::imgProcess(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    initUI();
    connect(ui.openButton, SIGNAL(clicked()), this, SLOT(openImg()));
    connect(ui.imgButton, SIGNAL(clicked()), this, SLOT(processImg()));
    connect(ui.detectButton, SIGNAL(clicked()), this, SLOT(SVMDetect()));
}


void imgProcess::openImg()//选择一张图片并打开
{
    ui.originalImg->clear(); //清除已有的图片的操作
    ui.processImg->clear();
    QString fileName = QFileDialog::getOpenFileName(this, "OpenFile", QDir::currentPath());
    if (fileName.isEmpty())
    {
        qDebug() << "error, please reselect" << endl;
        return;
    }
    else {
        //qDebug() << "img file: " << fileName << endl;
        QImage qimg;
        qimg.load(fileName);
        //qimg = qimg.scaled(ui.originalImg->size());// 图片使用label尺寸,检测效果不好,改变了尺寸
        cvimg = QCTransfer(qimg);//qt图像 转 opencv mat 矩阵
        //qDebug() << qimg.format() << endl;
        ui.originalImg->resize(qimg.size());
        ui.originalImg->setPixmap(QPixmap::fromImage(qimg));

        //imshow("test", cvimg);
        //waitKey(0);
    }

}

void imgProcess::processImg()
{
    cvimg = imgP.to_gray(cvimg);
    //cout << "cvimg format" << cvimg.channels() << endl; //输出为1,表示一个通道的灰度图
    cvimg = imgP.img_process(cvimg);
    imgP.img_get(cvimg);//将每个疵点保存到文件夹


    //CV 图像 转 Qt 图像并在label 中显示
    QImage Qtemp = QImage((const unsigned char*)(cvimg.data), cvimg.cols, cvimg.rows, cvimg.step, QImage::Format_Grayscale8); 
    Qtemp = QImage((const unsigned char*)(cvimg.data), cvimg.cols, cvimg.rows, cvimg.step, QImage::Format_Grayscale8);
    //Qtemp = Qtemp.scaled(ui.processImg->size());// 图片使用label尺寸
    ui.processImg->setPixmap(QPixmap::fromImage(Qtemp));

    ui.processImg->resize(Qtemp.size());  // label 适应 image 尺寸
    ui.processImg->show();

}

void imgProcess::SVMDetect()
{
    Widget* w = new Widget();
    w->show();

}

SVM分类部分

.h

#pragma once

#include <QtWidgets/QWidget>
#include "ui_Widget.h"
#include <QDir>
#include <QFileDialog>
#include <QStringList>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget* parent = Q_NULLPTR);
    void Ui_Init();
    void SVM_Pre();//predict by SVM

private:
    Ui::Form ui;
};

.cpp

#include "Widget.h"
#include<iostream>
#include<opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
#include "img.h"


using namespace cv;
using namespace std;
using namespace cv::ml;

//建立类
img imgSVM; // 进行类的声明

//检测SVM检测部分
void Widget::SVM_Pre()
{
    Ptr<ml::SVM>svm = ml::SVM::load("svm.xml");
    int class1= 0;//三个类别的数目统计,先初始化为0
    int class2 = 0;
    int class3 = 0;
    // 使用CV 读取文件夹下的所有图片文件,尝试用qt 的方法,但是不太行
    String imgpath = "E:\\QtCv\\detect\\*.jpg";//要检查的文件夹及其文件类型
    vector<cv::String> image_files;
    glob(imgpath, image_files, false);
    cout << "cout : " << image_files.size() << endl;
    //开始遍历并进行检测数据的统计
    //cout << "file dir" <<image_files.at(0) << endl;
    
    Mat testImg;
    Mat testData(1, 3, CV_32F);//测试数据 1行 3列
    int tastLabel;
    for (int i = 0; i < image_files.size(); i++)
    {
        testImg = imread(image_files.at(i), 0);
        testData.at<float>(0, 0) = imgSVM.get_Area(testImg);
        testData.at<float>(0, 1) = imgSVM.get_wh(testImg);
        testData.at<float>(0, 2) = imgSVM.get_DutyRation(testImg);
        tastLabel = svm->predict(testData);
        switch (tastLabel)
        {
        case 1: class1++; break;
        case 2: class2++; break;
        case 3: class3++; break;
        }
    }

    QString c = QString::number(class1);
    ui.class1Num->clear();
    ui.class1Num->insertPlainText(c);
    c = QString::number(class2);
    ui.class2Num->clear();
    ui.class2Num->insertPlainText(c);
    c = QString::number(class3);
    ui.class3Num->clear();
    ui.class3Num->insertPlainText(c);

}

void Widget::Ui_Init() //UI界面初始化
{
    QImage longg;
    QImage point;
    QImage big;

    longg.load(":/Image/1.jpg");//加载长疵
    ui.class1Show->setPixmap(QPixmap::fromImage(longg));
    ui.class1Show->resize(longg.size());  // label 适应 image 尺寸
    ui.class1Show->show();

    //另外两个同理
    point.load(":/Image/point.jpg");//加载点疵,点疵图片已经放入资源文件
    //cout << point.format() << endl;
    ui.class2Show->setPixmap(QPixmap::fromImage(point));
    ui.class2Show->resize(point.size());  // label 适应 image 尺寸
    ui.class2Show->show();

    big.load(":/Image/2.jpg");//加载团疵
    ui.class3Show->setPixmap(QPixmap::fromImage(big));
    ui.class3Show->resize(big.size());  // label 适应 image 尺寸
    ui.class3Show->show();



}



Widget::Widget(QWidget* parent)
    : QWidget(parent)
{
    ui.setupUi(this);
    Ui_Init();
    SVM_Pre();
}

类函数部分

.h

#pragma once
#include<opencv2/opencv.hpp>
#include<iostream>


using namespace cv;
using namespace std;


class img
{
public:
	Mat to_gray(Mat& image);//图像灰度处理
	Mat img_process(Mat& image);//预处理
	Mat img_num(Mat& image);//返回计数一个疵点图

	void img_get(Mat& image);//疵点保存文件夹
	float get_Area(Mat& iamge);//统计白色像素点的个数
	float get_wh(Mat& image);//宽高之比
	float get_DutyRation(Mat& image);//返回疵点图像的占空比



private:
	int w; // 图像的宽度,类内部的函数都可以调用
	int h; //图像的高度

};

.cpp

#include "img.h"


//图像灰度处理
Mat img::to_gray(Mat& image)
{
	Mat dst;
	cvtColor(image,dst, COLOR_RGB2GRAY); //转为灰度
	return dst;
}

//图像预处理
Mat img::img_process(Mat& image)
{
	Mat dst;
	GaussianBlur(image, dst, Size(3, 3), 0, 0);

	threshold(dst, dst, 188, 255, THRESH_BINARY); // 阈值,手动调节bar获得
	Mat element = getStructuringElement(MORPH_RECT, Size(2, 2));
	morphologyEx(dst, dst, MORPH_OPEN, element);

	return dst;
}


Mat img::img_num(Mat& image)
{
	Mat dst;
	dst = image;
	vector<vector<Point> > contours;//检测到的轮廓,每条轮廓线都以点向量的形式存储
	vector<Vec4i> hierarchy;//包含有关图像拓扑的信息
	findContours(image, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE, Point());
	int i = 0;
	int j = 1;
	for (i = 0; i < contours.size(); i++) {
		Rect fRect = boundingRect(contours[i]);
		int x_pontl = fRect.x - 5;
		int y_pontl = fRect.y - 5;
		int x_pontr = fRect.x + fRect.width + 2;
		int y_pontr = fRect.y + fRect.height + 2;

		int area = fRect.height * fRect.width;
		if (area >= 5) {


			rectangle(dst, Point(x_pontl, y_pontl), Point(x_pontr, y_pontr), Scalar(255), 1);
			string text = to_string(j);
			putText(dst, text, Point(x_pontl, y_pontl), FONT_HERSHEY_SIMPLEX, 0.4, (255), 1);
			j++;

		}

	}
	return dst;
}

string imgfile = "E:\\Qt Cv\\detect\\";
string imgName;

//50*50 模板的尺寸
//图像融合 传入的图像与50*50 的进行融合
Mat img_resize(Mat& image, int& w, int& h)
{
	Mat black_img = Mat::zeros(Size(50, 50), CV_8UC1);//黑色图像
	Mat imgROI;
	int x = 25 - (w / 2);
	int y = 25 - (h / 2);
	imgROI = black_img(Rect(x, y, w, h));
	addWeighted(imgROI, 0.1, image, 0.9, 0, imgROI);
	return black_img;

}

void img::img_get(Mat& image)
{
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(image, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
	int i = 0;
	int j = 1;
	int w_roi, h_roi;
	Mat roi;
	Mat img_wr;
	for (i = 0; i < contours.size(); i++) {
		Rect frect = boundingRect(contours[i]); // 轮廓的面积
		//坐标修改
		int area = frect.height * frect.width;

		if (area >= 10) {

			Rect rec(frect.x, frect.y, frect.width, frect.height);
			roi = image(rec);
			w_roi = roi.cols;
			h_roi = roi.rows;
			cout << j << "尺寸" << w_roi << "*" << h_roi << endl;
			//将其变为正确的尺寸
			img_wr = img_resize(roi, w_roi, h_roi);
			imgName = imgfile + to_string(j) + ".jpg";
			j++;
			imwrite(imgName, img_wr);
		}

	}


}


float img::get_Area(Mat& iamge)
{
	threshold(iamge, iamge, 0, 255, THRESH_BINARY);
	float area = 0.;
	//通过迭代器访问图像的像素点
	Mat_<uchar>::iterator itor = iamge.begin<uchar>();
	Mat_<uchar>::iterator itorEnd = iamge.end<uchar>();
	for (; itor != itorEnd; itor++) {
		if ((*itor) > 254) {
			//白色像素
			area++;
		}

	}
	return area;


}

float img::get_wh(Mat& image)
{
	float w, h;
	threshold(image, image, 0, 255, THRESH_BINARY);
	float ration;// 返回的宽 高 之比, 长条形 宽大于高
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
	morphologyEx(image, image, MORPH_OPEN, element);
	vector<vector<Point> > contours;//检测到的轮廓,每条轮廓线都以点向量的形式存储
	vector<Vec4i> hierarchy;//包含有关图像拓扑的信息
	findContours(image, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE, Point());
	for (int i = 0; i < contours.size(); i++) {
		Rect rects = boundingRect(contours[i]);
		int area = rects.width * rects.height;
		if (area > 10) {//排除过小的噪声被当成轮廓
			w = rects.width;
			h = rects.height;
		}
	}
	ration = w / h;
	return ration;

}


float img::get_DutyRation(Mat& image)
{
	float duty_ration;
	int imageW = image.cols;
	int imageH = image.rows;
	float imageArea = imageW * imageH;
	float foreArea = get_Area(image);//前景图像的面积,彩色像素的面积
	duty_ration = foreArea / imageArea;


	return  duty_ration;

}

主函数部分

#include "imgProcess.h"
#include <QtWidgets/QApplication>
#include<opencv2/opencv.hpp>
#include<iostream>
#include<string.h>



using namespace cv;
using namespace std;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
   

    //创建窗口程序
    imgProcess w;
    w.show();
    return a.exec();
}

效果

 

链接

百度网盘整个文件

链接:https://pan.baidu.com/s/13vNzjWO4Rv_rrDWVM2-0pw 
提取码:g1lv

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值