最短路径提取¶
一个 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++;
}
}