Почему я не могу правильно генерировать коронарные и сагиттальные срезы из вектора из 256 КТ-изображений, используя свой код на C++?

Вопрос или проблема

Загрузка 256 КТ-изображений 512*512 поперечных срезов и размещение их в векторе<mat>(256),

 Handler(std::string path) {
     pixel_array.reserve(slice_num);
     for (int i = 0; i < slice_num; i++) {
         std::ostringstream oss;
         oss << path << i << ".png";
         cv::Mat img = cv::imread(oss.str(),cv::IMREAD_UNCHANGED);//это изображение имеет 16-битную глубину цвета 
         if (img.empty()) {
             std::cerr << "Не удалось загрузить изображение: " << oss.str() << std::endl;
         }
         else
         {
             pixel_array.push_back(img);//добавить изображение в вектор
         }
     }
 }

затем получение корональных и сагиттальных срезов с помощью следующего кода:

// Получить корональный срез  
std::vector<cv::Mat> get_coronal() {  
    std::vector<cv::Mat> coronal_section(slice_height, cv::Mat(slice_num, slice_width, CV_16UC1, cv::Scalar(0)));  
    for (int i = 0; i < slice_height; i++)  
    {  
        for (int k = 0; k < slice_num; k++)  
        {  
            pixel_array[k].row(i).copyTo(coronal_section[i].row(k));  
        }  
    }  
    return coronal_section;  
}  
  
// Получить сагиттальный срез  
std::vector<cv::Mat> get_sagittal() {  
    std::vector<cv::Mat> sagittal_section(slice_width, cv::Mat(slice_height, slice_num, CV_16UC1, cv::Scalar(0)));  
    for (int j = 0; j < slice_width; j++)  
    {  
        for (int k = 0; k < slice_num; k++)  
        {  
            pixel_array[k].col(j).copyTo(sagittal_section[j].col(k));  
        }  
    }  
    return sagittal_section;  
}
 //получить поперечный срез
 std::vector<cv::Mat> get_transverse()
 {
     return pixel_array;
 }

Я использовал imshow для отображения поперечных, корональных и сагиттальных срезов, но корональные и сагиттальные срезы не удавалось корректно отобразить. Я попытался изменить их типы данных вектора на (CV_8UC1), но результаты стали еще хуже. Подозреваю, что может быть проблема с процессом копирования данных.это результат。ниже показано, как я использую imshow для этих изображений(девяносто первый срез)

void showslice()
{
    std::vector<cv::Mat>transverse(slice_num), cornoal(slice_height), sagittal(slice_width);
    transverse = get_transverse();
    cornoal = get_coronal();
    sagittal = get_sagittal();
    cv::namedWindow("transverse", cv::WINDOW_AUTOSIZE);
    cv::namedWindow("coronal", cv::WINDOW_AUTOSIZE);
    cv::namedWindow("sagittal", cv::WINDOW_AUTOSIZE);
    cv::imshow("transverse", transverse[90]);
    cv::imshow("coronal", cornoal[90]);
    cv::imshow("sagittal", sagittal[90]);

}

после изменения двух функций изображение отображается корректно.

std::vector<cv::Mat> get_coronal() {
    std::vector<cv::Mat> coronal_section(slice_width);
    for (int i = 0; i < slice_width; i++) {
        cv::Mat slice(slice_num, slice_height, CV_16UC1);
        for (int j = 0; j < slice_num; j++) {
            pixel_array[j].row(i).copyTo(slice.row(j));
        }
        coronal_section[i] = slice;
    }
    return coronal_section;
}

std::vector<cv::Mat> get_sagittal() {
    std::vector<cv::Mat> sagittal_section(slice_height);
    for (int i = 0; i < slice_height; i++) {
        cv::Mat slice(slice_width,slice_num , CV_16UC1);
        for (int j = 0; j < slice_num; j++) {
            pixel_array[j].col(i).copyTo(slice.col(j));
        }
        sagittal_section[i] = slice;
    }
    return sagittal_section;
}

введите описание изображения здесь

Ответ или решение

Ваша проблема с неправильным отображением корональных и сагиттальных срезов из вектора 256 КТ изображений может быть связана с несколькими аспектами вашего кода и логики обработки изображений. Рассмотрим эти аспекты подробно, чтобы выявить возможные источники ошибок и предложить эффективные решения.

1. Неправильное создание и заполнение новых матриц

Первое, что стоит отметить, — это создание матриц для хранения корональных и сагиттальных срезов. В вашем изначальном коде get_coronal() и get_sagittal(), вы создавали векторы, которые не полностью соответствовали требуемым параметрам.

Корональные срезы

Ваш изначальный фрагмент кода:

std::vector<cv::Mat> get_coronal() {
    std::vector<cv::Mat> coronal_section(slice_height, cv::Mat(slice_num, slice_width, CV_16UC1, cv::Scalar(0)));

в нем выделялось место для slice_height матриц, каждая из которых имела размер slice_num x slice_width. В результате coronal_section[i] фактически содержал пустую матрицу, что неприемлемо для последующей обработки.

Исправленный код

В исправленных функциях вы корректно объявляете матрицы для корональных и сагиттальных срезов. В каждом цикле for, куда вы заполняете эти матрицы, это помогает создать полноценные 2D представления срезов:

std::vector<cv::Mat> get_coronal() {
    std::vector<cv::Mat> coronal_section(slice_width);
    for (int i = 0; i < slice_width; i++) {
        cv::Mat slice(slice_num, slice_height, CV_16UC1);
        for (int j = 0; j < slice_num; j++) {
            pixel_array[j].row(i).copyTo(slice.row(j));
        }
        coronal_section[i] = slice;
    }
    return coronal_section;
}

Такой подход способствует корректному заполнению матриц.

2. Обработка данных с 16-битной глубиной цвета

Проблема может быть также связана с тем, что у ваших изображений есть 16-битная глубина цвета, а OpenCV по умолчанию может не поддерживать 16-битные изображения в случае некоторых операций. Использование CV_8UC1 для преобразования может привести к потере информации, так как диапазон значений 16-битного изображения (0-65535) не может корректно быть представлен в 8-битном (0-255).

Рекомендуется оставить целочисленные матрицы 16-битные (CV_16UC1), и обработать данные с учетом этой глубины.

3. Проверка параметров при отображении

Когда вы используете imshow для отображения корональных и сагиттальных срезов, необходимо удостовериться, что индекс 90, который вы используете для доступа к элементам вектора, не превышает количество доступных срезов в массиве. Например, если размер вектора срезов меньше 91 (например, если у вас только 90 срезов), это приведет к обращению к недоступной памяти.

4. Итоговая структура и оптимизация

Чтобы избежать дальнейших ошибок, предварительно проверьте размеры и типы данных каждого изображения после их загрузки. Кроме того, разумно вести логи для отслеживания любых ошибок, которые могли бы возникнуть в процессе обработки изображений.

Примерно вот так:

if (img.type() != CV_16UC1) {
    std::cerr << "Image format error at: " << oss.str() << std::endl;
}

Это поможет в диагностике.

Заключение

Таким образом, исправив логику создания и заполнения матриц для корональных и сагиттальных срезов, удостоверившись в правильной передаче типов данных и обратив внимание на индексы при отображении, вы сможете корректно генерировать и отображать необходимые срезы КТ. Применение данных рекомендаций должно значительно улучшить качество и точность представления ваших медицинских изображений.

Оцените материал
Добавить комментарий

Капча загружается...