599 lines
23 KiB
C++
599 lines
23 KiB
C++
#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));
|
||
}
|
||
}
|
||
}
|