EmbHMI/sharedviews/visualdetectwidget.cpp
2024-02-06 14:27:07 +08:00

599 lines
23 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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));
}
}
}