EmbHMI/sharedviews/visualdetectwidget.cpp

599 lines
23 KiB
C++
Raw Normal View History

2024-02-06 06:27:07 +00:00
#include "visualdetectwidget.h"
#include "ui_visualdetectwidget.h"
VisualDetectWidget::VisualDetectWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::VisualDetectWidget)
{
ui->setupUi(this);
setWindowFlags (Qt::Window | Qt::FramelessWindowHint);
setWindowModality(Qt::ApplicationModal);
initialize();
initControl();
m_imgPath = "";
m_globalFlag = 0; //定义全局变量标志位;
grayScale(); //灰度化与二值化;
//on_buttonLoadImage_clicked();//加载图片;
}
VisualDetectWidget::~VisualDetectWidget()
{
delete ui;
}
void VisualDetectWidget::initialize()
{
}
void VisualDetectWidget::initControl()
{
//根据不同分辨率设置控件的位置和尺寸
switch (g_emResolut)
{
case resolution1910:
initResolution1910();
break;
case resolution1006:
this->resize(1024,600);
break;
default:
initResolution1910();
break;
}
initControlStyle();//初始化窗体控件样式
}
void VisualDetectWidget::initResolution1910()
{
this->resize(600,680);
this->move((1920-this->width())/2,(1080-this->height())/2);
ui->labelImage->setGeometry(20,20,560,560);
ui->framePageBtn->setGeometry(422,610,168,70);
ui->buttonBack->setGeometry(0,0,168,70);
}
void VisualDetectWidget::initControlStyle()
{
SetControlStyle setControlStyle;
setControlStyle.setUiName(this->objectName());
ui->buttonBack->setBottomImage(setControlStyle.getSharedBottomStyleSheet(ui->buttonBack->parent()->objectName()));
ui->buttonBack->setTopImage(setControlStyle.getSharedTopStyleSheet(ui->buttonBack->objectName()));
}
#if(0)
void VisualDetectWidget::loadVisualDetectImage()
{
QDir apppath(qApp->applicationDirPath());
QString ImagePath = apppath.path() + apppath.separator() + "Image.png";
QImage image;
image.load(ImagePath);
QPixmap pix = QPixmap::fromImage(image);
ui->labelImage->setPixmap(pix);
#ifdef Q_OS_WIN
int x = image.width();
int y = image.height();
std::vector<QRgb> v1(x,1);
std::vector<std::vector<QRgb>> v2(y,v1);
for(int i = 0; i < y; i++)
{
for(int j = 0; j < x; j++)
{
QRgb pixel = image.pixel(j,i);
v2[i][j] = pixel;
}
}
#endif
}
#endif
//将彩色图片转换为黑白图片;
void VisualDetectWidget::grayScale()
{
QDir apppath(qApp->applicationDirPath());
QString path = apppath.path() + apppath.separator() + "Photograph" + apppath.separator() + "image.jpg";
QFile imgFile(path);
if(!imgFile.exists())//不存在照片
{
return;
}
QImage *img = new QImage();
img->load(path);
unsigned int * data = (unsigned int *)img->bits();
int size = img->width()*img->height();
int red;
int green;
int blue;
for(int i = 0; i < size; i++)
{
red = qRed(data[i]) * 0.3;
green = qGreen(data[i]) * 0.59;
blue = qBlue(data[i]) * 0.11;
int rgb = red + green + blue;
if(rgb > 80)
{
rgb = 255;
}
else
{
rgb =0;
}
data[i] = qRgba(rgb,rgb,rgb,qAlpha(data[i]));
}
QString pathSave = apppath.path() + apppath.separator() + "images_save.png";
m_imgPath = pathSave;
img->save(pathSave);//保存二值化后的图片;
QImage *image = new QImage();
image->load(pathSave);
int width = image->width();
int height = image->height();
int labelWidth = ui->labelImage->width();
int labelHeight = ui->labelImage->height();
int imgWidth = 0;
int imgHeight = 0;
float labelScale = (labelWidth *1.0)/(labelHeight*1.0);
float pictureScale = (width *1.0)/(height *1.0);
qDebug()<<labelScale<<"labelScale"<< pictureScale<<"pictureScale";
if(labelScale > pictureScale)
{
imgHeight = labelHeight;
imgWidth = labelHeight * pictureScale;
}
else
{
imgWidth = labelWidth;
imgHeight = labelWidth / pictureScale;
}
QPixmap *pixmap = new QPixmap;
QPixmap pix = pixmap->fromImage(*image);
pix= pix.scaled(imgWidth,imgHeight);
ui->labelImage->setPixmap(pix);
m_globalFlag =1;//灰度化转换完成
}
void VisualDetectWidget::on_buttonBack_clicked()
{
this->close();
}
//加载图片功能;
void VisualDetectWidget::on_buttonLoadImage_clicked()
{
QString path = QFileDialog::getOpenFileName(this,tr("Select file"),"D:",tr("PNG(*.png)"));
m_imgPath = path;
QImage *image = new QImage();
image->load(path);
int width = image->width();
int height = image->height();
int labelWidth = ui->labelImage->width();
int labelHeight = ui->labelImage->height();
int imgWidth = 0;
int imgHeight = 0;
float labelScale = (labelWidth * 1.0) / (labelHeight * 1.0);
float pictureScale = (width * 1.0) / (height * 1.0);
if(labelScale > pictureScale)
{
imgHeight = labelHeight;
imgWidth = labelHeight * pictureScale;
}
else
{
imgWidth = labelWidth;
imgHeight = labelWidth / pictureScale;
}
QPixmap *pixmap= new QPixmap;
QPixmap pp= pixmap->fromImage(*image);
pp = pp.scaled(imgWidth,imgHeight);
ui->labelImage->setPixmap(pp);
m_globalFlag =1;
}
//识别点的个数;
void VisualDetectWidget::on_buttonGetPointNumber_clicked()
{
//获取给定的最大与最小的个数;
QString str = ui->lineEdit_maxNumber->text();
int maxCount = str.toInt();
QString str2 = ui->lineEdit_minNumber->text();
int minCount = str2.toInt();
QString outStr;
//对话框;
QMessageBox *box = new QMessageBox();
//1.判断用户是否已经加载了图片;
if(m_globalFlag == 0)
{
outStr = "请先加载图片";
box->information(this,"错误",outStr);
}
else
{
//判断用户是否填写输入框;
//1将字符串转化为列表
QStringList list1 = str.split("");
QStringList list2 = str2.split("");
//2)判断列表是否为空;
if(list1.size() == 2 || list2.size() == 2)
{
//弹出对话框,提示“请输入最大与最小值”
outStr = "输入框为空,请输入最大与最小值";
box->information(this,"错误",outStr);
}
else
{
//循环遍历列表判断数值是否在0~9之间如不在弹出提示框若在则进行判断点的识别
//循环判断第一个输入框的列表;
for(int i = 1; i < list1.size() - 1; i++)
{
QString tmp = list1.at(i);
qDebug()<<"tmp="<<tmp;
if(tmp < "0" || tmp > "9")
{
//提示请在输入框1中输入在0~9之间的数字
//qDebug()<<"please input number from 0 to9 in lineEdit1";
outStr = "最大最小值输入错误";
box->information(this,"错误",outStr);
return;
}
}
//循环判断第二个输入框的列表;
for(int j = 1; j < list2.size() - 1; j++)
{
QString tmp2 = list2.at(j);
qDebug()<<"tmp2"<<tmp2;
if(tmp2 < "0" || tmp2 > "9")
{
//提示请在输入框2中输入在0~9之间的数字
//qDebug()<<"please input number from 0 to9 in lineEdit2";
outStr = "最大最小值输入错误";
box->information(this,"错误",outStr);
return;
}
}
//----------------------进行判断点的识别-----------------------
//获取原图像;
QString path = m_imgPath ;
QImage *image = new QImage();
image->load(path);
//1.获取图像像素字节数据的首地址 ---将二值化图像转换为数组
unsigned int *data = (unsigned int *)image->bits();
int width =image->width();//图像宽;
int height = image->height();//图像高;
int red;
int green;
int blue;
int pointHeight = 0;
int pointWidth = 0;
int pointNum = 0;
int size = width * (height - 12);//获取数组的个数;
for(int i = 1; i < size; i++)
{
red = qRed(data[i]);
green = qGreen(data[i]);
blue = qBlue(data[i]);
//判断该像素 是否是合格点的第一个像素,符合才需要进行宽与高的计算;
if(red == 255 && green == 255 && blue == 255)
{
int frontRed = qRed(data[i-1]);
int frontGreen = qGreen(data[i-1]);
int frontBlue = qBlue(data[i-1]);
//判断该像素的前一个像素是否为黑色;
if(frontRed == 0 && frontGreen == 0 && frontBlue == 0)
{
int temp = i;
//qDebug()<<temp<<"white";
int flag = 1;
//判断该像素的上面的7个像素是否为连续黑色
for(int j = 0; j < 7; j++)
{
int upRed = qRed(data[temp - width + j]);
int upGreen = qGreen(data[temp - width + j]);
int upBlue = qBlue(data[temp - width + j]);
if(upRed == 255 && upGreen == 255 && upBlue == 255)
{
flag = 0;
break;
//qDebug()<<"该像素上面的7个点不是连续的black,第"<<temp-width+j<<"is white";
}
}
//如果这七个像素都为黑色,则计算该点的宽与高;
if(flag)
{
//qDebug()<<"maybe a point";
//判断该像素 后面的几个像素是否为白色,如果是白色,记录个数;
int tempNum = 0;
tempNum = temp;
int nextRed = qRed(data[tempNum]);
int nextGreen = qGreen(data[tempNum]);
int nextBlue = qBlue(data[tempNum]);
while(nextRed == 255 && nextGreen == 255 && nextBlue == 255)
{
tempNum++;
nextRed = qRed(data[tempNum]);
nextGreen = qGreen(data[tempNum]);
nextBlue = qBlue(data[tempNum]);
}
int count;
count = tempNum - temp;
//qDebug()<<count<<"count";
int midNum = 0;
int midNumber = 0;
int tempMid = 0;
int bottomRed;
int bottomGreen;
int bottomBlue;
//计算中间值;
if(count % 2 != 0)
{
//如果是奇数;
midNum = (temp + tempNum - 1) / 2;//计算出中间值的坐标
//计算该列有多高;
int m = 1;
bottomRed = qRed(data[midNum + width]);
bottomGreen = qRed(data[midNum + width]);
bottomBlue = qRed(data[midNum + width]);
while(bottomRed == 255 && bottomGreen == 255 && bottomBlue == 255)
{
m++;
bottomRed = qRed(data[midNum + m * width]);
bottomGreen = qRed(data[midNum + m * width]);
bottomBlue = qRed(data[midNum + m * width]);
}
//高则为m的值
pointHeight = m;
tempMid = midNum;
}
else
{
//如果是偶数;
midNum = (temp + tempNum - 1) / 2;
midNumber = midNum + 1;
//需要计算出这两列的高;
int n = 1;
bottomRed = qRed(data[midNum + width]);
bottomGreen = qRed(data[midNum + width]);
bottomBlue = qRed(data[midNum + width]);
while(bottomRed == 255 && bottomGreen == 255 && bottomBlue == 255)
{
n++;
bottomRed = qRed(data[midNum + n * width]);
bottomGreen = qRed(data[midNum + n * width]);
bottomBlue = qRed(data[midNum + n * width]);
}
int k = 1;
bottomRed = qRed(data[midNumber + width]);
bottomGreen = qRed(data[midNumber + width]);
bottomBlue = qRed(data[midNumber + width]);
while(bottomRed == 255 && bottomGreen == 255 && bottomBlue == 255)
{
k++;
bottomRed = qRed(data[midNumber + k * width]);
bottomGreen = qRed(data[midNumber + k * width]);
bottomBlue = qRed(data[midNumber + k * width]);
}
// qDebug()<<"n的值为"<<n;
// qDebug()<<"k的值为"<<k;
//比较这两者之间的大小;
if(n < k)
{
pointHeight = k;
tempMid = midNumber;
}
else if(n > k)
{
pointHeight = n;
tempMid = midNum;
}
else
{
pointHeight = n;
tempMid = midNum;
}
}
//对高取中间值,从而计算宽度;
int mid = 0;
int midFront = 0;
int countNum = 0;
int leftRed;
int leftGreen;
int leftBlue;
int rightRed;
int rightGreen;
int rightBlue;
if(pointHeight % 2 != 0)
{
//如果行高数为奇数
countNum = pointHeight / 2;
mid = midNum + countNum * width;
leftRed = qRed(data[mid]);
leftGreen = qGreen(data[mid]);
leftBlue = qBlue(data[mid]);
rightRed = qRed(data[mid]);
rightGreen = qGreen(data[mid]);
rightBlue = qBlue(data[mid]);
//根据中间坐标判断左右是否为白色,然后计算宽度;
int k = 0;
//qDebug()<<"k的值为"<<k;
while(leftRed == 255 && leftGreen == 255 && leftBlue == 255)
{
k++;
leftRed = qRed(data[mid - k]);
leftGreen = qGreen(data[mid - k]);
leftBlue = qBlue(data[mid - k]);
}
//左侧的个数为k-1;
int m = 0;
while(rightRed == 255 && rightGreen == 255 && rightBlue == 255)
{
m++;
rightRed = qRed(data[mid + m]);
rightGreen = qGreen(data[mid + m]);
rightBlue = qBlue(data[mid + m]);
}
//右侧的个数为m+1;
//所以宽为左侧个数+1+右侧个数;
pointWidth = k + m + 1;
}
else
{
//如果高为偶数
countNum = pointHeight / 2;
mid = tempMid + countNum * width;
midFront = tempMid + (countNum - 1) * width;
leftRed = qRed(data[mid]);
leftGreen = qGreen(data[mid]);
leftBlue = qBlue(data[mid]);
rightRed = qRed(data[mid]);
rightGreen = qGreen(data[mid]);
rightBlue = qBlue(data[mid]);
//根据中间坐标判断左右是否为白色,然后计算宽度;
int temp_width = 0;
int temp_width2 = 0;
//1.判断左侧的个数
int k = 0;
while(leftRed == 255 && leftGreen == 255 && leftBlue == 255)
{
k++;
leftRed = qRed(data[mid - k]);
leftGreen = qGreen(data[mid - k]);
leftBlue = qBlue(data[mid - k]);
}
//左侧的个数为k-1;
//2.判断右侧的个数;
int m = 0;
while(rightRed == 255 && rightGreen == 255 && rightBlue == 255)
{
m++;
rightRed = qRed(data[mid + m]);
rightGreen = qGreen(data[mid + m]);
rightBlue = qBlue(data[mid + m]);
}
//右侧的个数为m+1;
//所以宽为左侧个数+1+右侧个数;
temp_width = k + m + 1;
//qDebug()<<temp_width<<"temp_width";
//-----------------计算第一行的宽度------
leftRed = qRed(data[midFront]);
leftGreen = qGreen(data[midFront]);
leftBlue = qBlue(data[midFront]);
rightRed = qRed(data[midFront]);
rightGreen = qGreen(data[midFront]);
rightBlue = qBlue(data[midFront]);
//根据中间坐标判断左右是否为白色,然后计算宽度;
int t = 0;
while(leftRed == 255 && leftGreen == 255 && leftBlue == 255)
{
t++;
leftRed = qRed(data[midFront - t]);
leftGreen = qGreen(data[midFront - t]);
leftBlue = qBlue(data[midFront - t]);
}
//左侧的个数为k-1;
int mm = 0;
while(rightRed == 255 && rightGreen == 255 && rightBlue == 255)
{
mm++;
rightRed = qRed(data[midFront + mm]);
rightGreen = qGreen(data[midFront + mm]);
rightBlue = qBlue(data[midFront + mm]);
}
//右侧的个数为m+1;
//所以宽为左侧个数+1+右侧个数;
temp_width2= t + mm + 1;
//qDebug()<<temp_width2<<"tempWidth2";
//比较这两者的大小;
int max;
if(temp_width < temp_width2)
{
max = temp_width2;
}
else if(temp_width > temp_width2)
{
max = temp_width;
}
else
{
max = temp_width;
}
pointWidth = max;
}
//比较计算得到的最大高度与宽度 是否在给定的最大直径和最小直径;
if(pointHeight >= minCount && pointHeight <= maxCount)
{
if(pointWidth >= minCount && pointWidth <= maxCount)
{
pointNum++;
}
}
}
}
}
}
//将点的个数显示在对应的label中
ui->labelPointSum->setText(QString("%1").arg(pointNum));
}
}
}