Skip to content

最短路径提取

一个 ITK 模块 Fast Marching Minimal Path Extraction in ITK ,它实现了基于 Fast Marching 到达函数的最小路径提取框架。框架输入 float 类型并压缩后的 zraw 图片,输出一组点。

将其工程化一下,做成一个前端。

QImage OpencvImgChange::cvMat2QImage(const Mat &mat) {  // Mat 改成 QImage
    if (mat.type() == CV_8UC1) {                // 单通道
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        image.setColorCount(256);               // 灰度级数256
        for (int i = 0; i < 256; i++) {
            image.setColor(i, qRgb(i, i, i));
        }
        uchar *pSrc = mat.data;                 // 复制mat数据
        for (int row = 0; row < mat.rows; row++) {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }

    else if (mat.type() == CV_8UC3) {           // 3通道
        const uchar *pSrc = (const uchar *)mat.data;            // 复制像素
        QImage image(pSrc, mat.cols, mat.rows, (int)mat.step, QImage::Format_RGB888);   // R, G, B 对应 0,1,2
        return image.rgbSwapped();              // rgbSwapped是为了显示效果色彩好一些。
    } else if (mat.type() == CV_8UC4) {
        const uchar *pSrc = (const uchar *)mat.data;            // 复制像素
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, (int)mat.step, QImage::Format_ARGB32);       // B,G,R,A 对应 0,1,2,3
        return image.copy();
    } else {
        return QImage();
    }
}

Mat OpencvImgChange::QImage2cvMat(QImage image) {       // QImage改成Mat
    Mat mat;
    switch (image.format()) {
    case QImage::Format_ARGB32:
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32_Premultiplied:
        mat = Mat(image.height(), image.width(), CV_8UC4, (void *)image.constBits(), image.bytesPerLine());
        break;
    case QImage::Format_RGB888:
        mat = Mat(image.height(), image.width(), CV_8UC3, (void *)image.constBits(), image.bytesPerLine());
        cv::cvtColor(mat, mat, CV_BGR2RGB);
        break;
    case QImage::Format_Indexed8:
    case QImage::Format_Grayscale8:
        mat = Mat(image.height(), image.width(), CV_8UC1, (void *)image.constBits(), image.bytesPerLine());
        break;
    }
    return mat;
}
QImage OpencvGray::Graylevel(QImage src) {              // 灰度图像
    Mat srcImg, dstImg;
    srcImg = imgchangeClass->QImage2cvMat(src);
    dstImg.create(srcImg.size(), srcImg.type());
    if (srcImg.channels() != 1) {
        cvtColor(srcImg, dstImg, CV_BGR2GRAY);
    } else {
        dstImg = srcImg.clone();
    }
    if (IsBin(dstImg)) {
        BinToGraylevel(dstImg);
    }
    QImage dst = imgchangeClass->cvMat2QImage(dstImg);
    return dst;
}
oid OpencvGray::BinToGraylevel(Mat &image) {
    int w = image.cols;
    int h = image.rows;
    for (int row = 0; row < h; row++) {
        uchar *uc_pixel = image.data + row * image.step;
        for (int col = 0; col < w; col++) {
            if (uc_pixel[0] <= 20) {
                uc_pixel[0] = 50;
            }
            if (uc_pixel[0] >= 235) {
                uc_pixel[0] = 150;
            }
            uc_pixel += 1;
        }
    }
}


QImage OpencvGray::Bin(QImage src, int threshold) {     // 二值化
    Mat srcImg, dstImg, grayImg;
    srcImg = imgchangeClass->QImage2cvMat(src);
    if (srcImg.channels() != 1) {
        cvtColor(srcImg, grayImg, CV_BGR2GRAY);
    } else {
        dstImg = srcImg.clone();
    }
    cv::threshold(grayImg, dstImg, threshold, 255, THRESH_BINARY);
    QImage dst = imgchangeClass->cvMat2QImage(dstImg);
    return dst;
}
    constexpr unsigned int Dimension = 2;
    using FloatType = float  ;
    using CharType = unsigned char  ;
    using ImageFloatType = itk::Image< FloatType, Dimension >;
    using ImageCharType = itk::Image< CharType, Dimension >;
    using ReaderType = itk::ImageFileReader< ImageFloatType >;
    using WriterType = itk::ImageFileWriter< ImageCharType >;
    using PathType = itk::PolyLineParametricPath< Dimension >;
    using PathFilterType =
        itk::SpeedFunctionToPathFilter< ImageFloatType, PathType >;
        using CoordRepType = PathFilterType::CostFunctionType::CoordRepType;
    using PathIteratorType = itk::PathIterator< ImageCharType, PathType >;

//读取速度功能
        ReaderType::Pointer reader = ReaderType::New();
        reader->SetFileName(&png_name_constchar);
        reader->Update();
        ImageFloatType::Pointer speed = reader->GetOutput();
        speed->DisconnectPipeline();
        ImageFloatType::SizeType size = speed->GetLargestPossibleRegion().GetSize();
        ImageFloatType::IndexType pixelIndex;
        for (int i = 0; i < static_cast<int>(size[0]); i++) {
            for (int j = 0; j < static_cast<int>(size[1]); j++) {
                pixelIndex[0] = i;
                pixelIndex[1] = j;
                speed->SetPixel(pixelIndex,  1 - (speed->GetPixel(pixelIndex) / 255));
            }
        }
void MainWindow::CreateImageWithOverlay(
    const QImage &baseImage, QImage &overlayImage) {
    QImage imageWithOverlay = QImage(overlayImage.size(),
                                     QImage::Format_ARGB32_Premultiplied);
    QPainter painter(&imageWithOverlay);
    painter.fillRect(overlayImage.rect(), Qt::transparent);
    painter.drawImage(0, 0, baseImage);
    painter.drawImage(0, 0, overlayImage);
    painter.end();
    overlayImage = imageWithOverlay;
}

void MainWindow::ConvertImageToTransparent(QImage &baseImage) {
    baseImage = baseImage.convertToFormat(QImage::Format_ARGB32);
    union myrgb {
        uint rgba;
        uchar rgba_bits[4];
    };
    myrgb *mybits = (myrgb *) baseImage.bits();
    qint32 len = baseImage.width() * baseImage.height();
    while (len -- > 0) {
        mybits->rgba_bits[0] = 0;
        mybits->rgba_bits[1] = 0;
        mybits->rgba_bits[2] = (mybits->rgba == 0xFF000000) ? 0 : 255;
        mybits->rgba_bits[3] = (mybits->rgba == 0xFF000000) ? 0 : 255;
        mybits++;
    }
}