代码拉取完成,页面将自动刷新
#include "mainwindow.h"
#include "ui_mainwindow.h"
using namespace cv;
using namespace std;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, currentIndex(0)
, isPlaying(false)
, isPlayingWhiteLineMethod(false)
{
ui->setupUi(this);
//设置旋钮
ui->dial->setNotchesVisible(true);
ui->dial->setMaximum(100);
ui->dial->setMinimum(0);
ui->dial->setValue(0);
// 设置定时器
// QTimer *timer = new QTimer(this);
// timer->start(1000);
// connect(timer,SIGNAL(timeout()),this,SLOT(mySetCurrentDateTime()));//1s触发一次更新时间的函数
speedTimer = new QTimer(this);
connect(speedTimer, &QTimer::timeout, this, &MainWindow::updateImage);
//设置progressBar
ui->progressBar->setValue(0);
//设置一开始白线列搜边方法的按钮为隐藏
ui->whiteLineMethod->hide();
}
MainWindow::~MainWindow()
{
delete ui;
}
// --------------------------一些工具函数--------------------------
/**
* @brief 自然排序,按照ascii码
* @param s1,某个串
* @param s2,某个串
* @return
*/
bool naturalSort(const QString &s1, const QString &s2)
{
QRegularExpression re("(\\d+)");
QRegularExpressionMatchIterator i1 = re.globalMatch(s1);
QRegularExpressionMatchIterator i2 = re.globalMatch(s2);
while (i1.hasNext() && i2.hasNext()) {
int n1 = i1.next().captured(0).toInt();
int n2 = i2.next().captured(0).toInt();
if (n1 != n2)
return n1 < n2;
}
return s1 < s2;
}
// --------------------------一些工具函数--------------------------
void MainWindow::on_dial_valueChanged(int value)
{
ui->lcdNumber->display(value);
}
void MainWindow::on_slider_valueChanged(int value)
{
if( isPlaying == false){
showImage(value);
ui->progressBar->setValue(value);
}
}
void MainWindow::on_readSD_clicked()
{
// 弹出文件选择对话框
QString folderPath = QFileDialog::getExistingDirectory(this, tr("选择保存图片的文件夹"), "");
// 判断用户是否选择了文件夹
if (folderPath.isEmpty()) {
QMessageBox::information(this, "Info", "未选择文件夹!");
return;
}
string imgName = folderPath.toStdString() + "/hello";
int imgNum = 1;
int fd = open("\\\\.\\E:", O_RDONLY | O_BINARY);
lseek64(fd, SECTOR_START * SECTOR_SIZE, SEEK_SET);//设置读取的起始位置,
// lseek函数需要与read配合使用,
// 每次read后会自动在前一次地址的基础上增加读取的长度
// lseek函数传SEEK_SET可设置当前偏移地址
do
{
if(fd != -1)
{
char imgGray_SDBuff[SECTOR_SIZE * SECTOR_NUM_IMGBUFF];
char imgGray_buff[ROW * COL];
/* 图像数组--->图片 */
read(fd, imgGray_SDBuff, sizeof(imgGray_SDBuff));// 图像读取 必须读512的整数倍
memcpy(imgGray_buff, imgGray_SDBuff, sizeof(imgGray_buff)); // 数组内容复制
cv::Mat mat(ROW, COL, CV_8UC1, imgGray_buff); // 图像数组 转换成 8bite灰度图
/* 文件命名 and 保存 */
String imgNameSave = imgName + to_string(imgNum) + ".bmp"; // 文件名
cv::imwrite(imgNameSave, mat); // 将图像保存到指定文件
++imgNum;
if(imgNum > 2000){
QMessageBox::information(this,"结束","以到达最大上限");
break;
}
}
else
{
qDebug() << "maybe don't have permission";
QMessageBox info;
info.critical(this,"Error","未查询到SD卡!");
break;
}
} while(1);
}
void MainWindow::on_readBMP_clicked()
{
folderPath = QFileDialog::getExistingDirectory(this, tr("选择BMP图片的文件夹"), "");
if (!folderPath.isEmpty()) {
loadImages(folderPath);
} else {
QMessageBox::information(this, "Info", "未选择文件夹!");
}
}
void MainWindow::loadImages(const QString &folderPath)
{
QDir dir(folderPath);
bmpFiles = dir.entryList(QStringList() << "*.bmp", QDir::Files, QDir::NoSort);
// 设置slider的一些属性
ui->slider->setMaximum(bmpFiles.size());
ui->slider->setMinimum(0);
ui->slider->setValue(0);
// 对文件名进行自然排序
std::sort(bmpFiles.begin(), bmpFiles.end(), naturalSort);
// 打印排序后的文件名列表
for (const QString &file : bmpFiles) {
qDebug() << "pictures: " << file;
}
if (bmpFiles.isEmpty()) {
QMessageBox::information(this, "Info", "该文件夹内没有BMP图片!");
} else {
currentIndex = 0;
showImage(currentIndex);
}
}
void MainWindow::showImage(int index)
{
if (!bmpFiles.isEmpty() && index >= 0 && index < bmpFiles.size()) {
// 构建完整的图片路径
QString filePath = QDir(folderPath).filePath(bmpFiles.at(index));
// 使用 OpenCV 读取 BMP 图片并转换为 cv::Mat
cv::Mat mat = cv::imread(filePath.toStdString(),IMREAD_GRAYSCALE);
if (mat.empty()) {
QMessageBox::warning(this, "Error", "无法加载图片: " + filePath);
return;
}
int height = mat.rows;
int weight = mat.cols;
// 将读取的mat格式转化成图片数组
for(int i = 0; i <height ; i++){
for(int j =0; j < weight ; j++){
mt9v03x_image[i][j] = mat.at<uint8_t>(i,j);
}
}
//制作二值化图
int otsuParam = otsuThreshold_fast(mt9v03x_image[0]);
setImageTwoValue(otsuParam);
// 判断要播放的是哪一个图片
int whichPicture = ui->whichPicture->currentIndex();
if( whichPicture == Original ){
QImage imgOriginal = QImage((uchar*)mt9v03x_image[0],weight,height,QImage::Format_Grayscale8);
ui->bmpShow->repaint();
ui->bmpShow->setPixmap(QPixmap::fromImage(imgOriginal).scaled(ui->bmpShow->size(),Qt::KeepAspectRatio));
}else if( whichPicture == Binary ){
//枚举各种状态
if( isPlayingWhiteLineMethod ){
ui->bmpShow->clear();
longestWhiteColumnSearchLines();
crossDetect();
islandDetect();
showBoundaryOnBinaryImage();
}else{// 最普通的情况
QImage imgBinary = QImage((uchar*)mt9v03x_image_Binary[0],weight,height,QImage::QImage::Format_Grayscale8);
ui->bmpShow->repaint();
ui->bmpShow->setPixmap(QPixmap::fromImage(imgBinary).scaled(ui->bmpShow->size(),Qt::KeepAspectRatio));
}
}else if( whichPicture == Compress){
cv::Mat compressedImage;
cv::resize(mat, compressedImage, cv::Size(47, 60)); // 注意,OpenCV 的 resize 函数是以 (宽, 高) 的形式
QImage img((uchar*)compressedImage.data, compressedImage.cols, compressedImage.rows, compressedImage.step, QImage::Format_Grayscale8);
ui->bmpShow->setPixmap(QPixmap::fromImage(img).scaled(ui->bmpShow->size(), Qt::KeepAspectRatio));
}
qDebug()<< "filepath:"<< filePath << endl;
}
}
void MainWindow::on_Play_clicked()
{
if(!bmpFiles.isEmpty() && isPlaying == false){
isPlaying = true;
int interval = ui->playSpeed->currentText().toDouble() * 1000;
speedTimer->start(static_cast<int>(interval));
}
}
void MainWindow::on_Pause_clicked()
{
if(isPlaying == true){
isPlaying = false;
speedTimer->stop();
}
}
void MainWindow::on_Prev_clicked()// 只能在暂停的时候切换上下张
{
if (!bmpFiles.isEmpty() && currentIndex > 0 && isPlaying == false) {
--currentIndex;
showImage(currentIndex);
}
}
void MainWindow::on_Next_clicked()// 只能在暂停的时候切换上下张
{
if (!bmpFiles.isEmpty() && currentIndex < bmpFiles.size() - 1 && isPlaying == false) {
++currentIndex;
showImage(currentIndex);
}
}
void MainWindow::updateImage()
{
if (!bmpFiles.isEmpty()) {
currentIndex = (currentIndex + 1) % bmpFiles.size();
showImage(currentIndex);
elementDetecting();
}
}
void MainWindow::showBoundaryOnBinaryImage()
{
// 假设当前显示的是二值化图像
cv::Mat matGray = cv::Mat(MT9V03X_H, MT9V03X_W, CV_8UC1, mt9v03x_image_Binary);
// 将灰度图转换为彩色图(3通道)
cv::Mat matColor;
cv::cvtColor(matGray, matColor, cv::COLOR_GRAY2BGR);
// 添加角点
// int x1 = findLeftDownPoint();
// int y1 = Left_Line[x1];
// int x2 = findLeftUpPoint();
// int y2 = Left_Line[x2];
// int x3 = findRightDownPoint();
// int y3 = Right_Line[x3];
// int x4 = findRightUpPoint();
// int y4 = Right_Line[x4];
// if(x1 && x2){
// qDebug() << "左下x:"<< x1 << ", 左下y:" << y1 << endl;
// qDebug() << "左上x:"<< x2 << ", 左上y:" << y2 << endl;
// qDebug() << "右下x:"<< x3 << ", 右下y:" << y3 << endl;
// qDebug() << "右上x:"<< x4 << ", 右下y:" << y4 << endl;
// }
// markPoint(matColor, y1, x1);
// markPoint(matColor, y2, x2);
// markPoint(matColor, y3, x3);
// markPoint(matColor, y4, x4);
// addLeftLine(x1, y1, x2, y2);
// addRightLine(x3, y3, x4, y4);
// 在彩色图像上绘制左、右边界线
for (int i = MT9V03X_H - 1; i > MT9V03X_H - Search_Stop_Line; i--) {
//if (Left_Line_Lost[i] == 0)
cv::circle(matColor, cv::Point(Left_Line[i], i), 1, cv::Scalar(0, 0, 255), -1);
//if (Right_Line_Lost[i] == 0)
cv::circle(matColor, cv::Point(Right_Line[i], i), 1, cv::Scalar(255, 0, 0), -1);
}
// 转换为 QImage 并显示在 QLabel 上
QImage img((uchar*)matColor.data, matColor.cols, matColor.rows, matColor.step, QImage::Format_RGB888);
img.rgbSwapped();
ui->bmpShow->setPixmap(QPixmap::fromImage(img).scaled(ui->bmpShow->size(), Qt::KeepAspectRatio));
ui->bmpShow->repaint(); // 刷新 QLabel
}
void MainWindow::on_gotoPage_clicked()// 只能在暂停的时候跳转
{
if(isPlaying == false){
currentIndex = ui->whichPage->text().toInt();
showImage(currentIndex);
}
}
void MainWindow::on_whichPicture_currentIndexChanged(const QString &arg1)
{
if(arg1 == "二值化图"){
ui->whiteLineMethod->show();
}else{
ui->whiteLineMethod->hide();
}
}
void MainWindow::on_whiteLineMethod_clicked()
{
isPlayingWhiteLineMethod = !isPlayingWhiteLineMethod;
if(isPlayingWhiteLineMethod){
ui->whiteLineMethod->setText("白线列巡线(开)"); // value == 1
}else{
ui->whiteLineMethod->setText("白线列巡线(关)"); // value == 0
}
}
void MainWindow::markPoint(cv::Mat &image, int x, int y) {
// 定义标记的颜色为绿色
cv::Scalar color(0, 255, 0); // 绿色
int thickness = 2;
int radius = 5;
// 在指定坐标处绘制一个圆形标记
cv::circle(image, cv::Point(x, y), radius, color, thickness);
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。