Exemple #1
0
/* Process the images inside each directory */
bool processDir(std::string path, std::string image_name, std::string metrics_file) {

    /** Create the initial data collection skeleton **/

    // Open the metrics file
    std::ofstream data_stream;
    data_stream.open(metrics_file, std::ios::app);
    if (!data_stream.is_open()) {
        std::cerr << "Could not open the data output file." << std::endl;
        return false;
    }

    // Create the output image directory
    std::string out_directory = path + "result/";
    struct stat st = {0};
    if (stat(out_directory.c_str(), &st) == -1) {
        mkdir(out_directory.c_str(), 0700);
    }

    // Analyzed image name
    std::string analyzed_image_name = image_name;
    std::size_t found = analyzed_image_name.find("dapi");
    analyzed_image_name.replace(found, 4, "merge");
    data_stream << analyzed_image_name << ",";

    /** Extract the dapi, gfp and rfp streams for each input image **/

    // DAPI
    std::string in_filename = path + "jpg/" + image_name;
    cv::Mat dapi = cv::imread(in_filename.c_str(), -1);
    if (dapi.empty()) return false;

    // GFP
    std::string gfp_image_name = image_name;
    found = gfp_image_name.find("dapi");
    gfp_image_name.replace(found, 4, "gfp");
    in_filename = path + "jpg/" + gfp_image_name;
    cv::Mat gfp = cv::imread(in_filename.c_str(), -1);
    if (gfp.empty()) return false;

    // RFP
    std::string rfp_image_name = image_name;
    found = rfp_image_name.find("dapi");
    rfp_image_name.replace(found, 4, "rfp");
    in_filename = path + "jpg/" + rfp_image_name;
    cv::Mat rfp = cv::imread(in_filename.c_str(), -1);
    if (rfp.empty()) return false;


    /** Gather information needed for feature extraction **/

    /* DAPI image */
    // Enhance
    cv::Mat dapi_normalized, dapi_enhanced;
    if (!enhanceImage(  dapi, 
                        ChannelType::DAPI, 
                        &dapi_normalized, 
                        &dapi_enhanced  )) {
        return false;
    }

    // Segment
    cv::Mat dapi_segmented;
    std::vector<std::vector<cv::Point>> contours_dapi;
    std::vector<cv::Vec4i> hierarchy_dapi;
    std::vector<HierarchyType> dapi_contour_mask;
    std::vector<double> dapi_contour_area;
    contourCalc(dapi_enhanced, ChannelType::DAPI, 1.0, 
                &dapi_segmented, &contours_dapi, 
                &hierarchy_dapi, &dapi_contour_mask, 
                &dapi_contour_area);

    // Filter the dapi contours
    std::vector<std::vector<cv::Point>> contours_dapi_filtered;
    filterCells(dapi_enhanced, contours_dapi, dapi_contour_mask, &contours_dapi_filtered);


    /* GFP image */
    cv::Mat gfp_normalized, gfp_enhanced;
    if (!enhanceImage(  gfp, 
                        ChannelType::GFP, 
                        &gfp_normalized, 
                        &gfp_enhanced   )) {
        return false;
    }

    // GFP Low
    cv::Mat gfp_low_normalized, gfp_low_enhanced;
    if (!enhanceImage(  gfp, 
                        ChannelType::GFP_LOW, 
                        &gfp_low_normalized, 
                        &gfp_low_enhanced   )) {
        return false;
    }
    cv::Mat gfp_low_segmented;
    std::vector<std::vector<cv::Point>> contours_gfp_low;
    std::vector<cv::Vec4i> hierarchy_gfp_low;
    std::vector<HierarchyType> gfp_low_contour_mask;
    std::vector<double> gfp_low_contour_area;
    contourCalc(gfp_low_enhanced, ChannelType::GFP_LOW, 1.0, 
                &gfp_low_segmented, &contours_gfp_low, 
                &hierarchy_gfp_low, &gfp_low_contour_mask, 
                &gfp_low_contour_area);

    // GFP Medium
    cv::Mat gfp_medium_normalized, gfp_medium_enhanced;
    if (!enhanceImage(  gfp, 
                        ChannelType::GFP_MEDIUM, 
                        &gfp_medium_normalized, 
                        &gfp_medium_enhanced   )) {
        return false;
    }
    cv::Mat gfp_medium_segmented;
    std::vector<std::vector<cv::Point>> contours_gfp_medium;
    std::vector<cv::Vec4i> hierarchy_gfp_medium;
    std::vector<HierarchyType> gfp_medium_contour_mask;
    std::vector<double> gfp_medium_contour_area;
    contourCalc(gfp_medium_enhanced, ChannelType::GFP_MEDIUM, 1.0, 
                &gfp_medium_segmented, &contours_gfp_medium, 
                &hierarchy_gfp_medium, &gfp_medium_contour_mask, 
                &gfp_medium_contour_area);

    // GFP High
    cv::Mat gfp_high_normalized, gfp_high_enhanced;
    if (!enhanceImage(  gfp, 
                        ChannelType::GFP_HIGH, 
                        &gfp_high_normalized, 
                        &gfp_high_enhanced   )) {
        return false;
    }
    cv::Mat gfp_high_segmented;
    std::vector<std::vector<cv::Point>> contours_gfp_high;
    std::vector<cv::Vec4i> hierarchy_gfp_high;
    std::vector<HierarchyType> gfp_high_contour_mask;
    std::vector<double> gfp_high_contour_area;
    contourCalc(gfp_high_enhanced, ChannelType::GFP_HIGH, 1.0, 
                &gfp_high_segmented, &contours_gfp_high, 
                &hierarchy_gfp_high, &gfp_high_contour_mask, 
                &gfp_high_contour_area);

    /* RFP image */
    cv::Mat rfp_normalized, rfp_enhanced_type1;
    if (!enhanceImage(  rfp, 
                        ChannelType::RFP_TYPE1, 
                        &rfp_normalized, 
                        &rfp_enhanced_type1 )) {
        return false;
    }
    cv::Mat rfp_enhanced_type2;
    if (!enhanceImage(  rfp, 
                        ChannelType::RFP_TYPE2, 
                        &rfp_normalized, 
                        &rfp_enhanced_type2 )) {
        return false;
    }
    cv::Mat rfp_segmented;
    std::vector<std::vector<cv::Point>> contours_rfp_vec;
    std::vector<cv::Vec4i> hierarchy_rfp;
    std::vector<HierarchyType> rfp_contour_mask;
    std::vector<double> rfp_contour_area;
    contourCalc(rfp_enhanced_type2, ChannelType::RFP_TYPE2, 1.0, 
                &rfp_segmented, &contours_rfp_vec, 
                &hierarchy_rfp, &rfp_contour_mask, 
                &rfp_contour_area);

    /* RFP Scatter plot */
    // Determine whether the image is Control or SZ
    bool is_control = false;
    std::string sample_id = image_name.substr(0, 4);
    // Control - 3440, 3651, 4506, 9319, 9429, BJ2E, BJ3E
    if (    (sample_id == "3440") ||
            (sample_id == "3651") ||
            (sample_id == "4506") ||
            (sample_id == "9319") ||
            (sample_id == "9429") ||
            (sample_id == "BJ2E") ||
            (sample_id == "BJ3E")  ) {
        is_control = true;
    }
    // Note: Do nothing for SZ - 1792, 1835, 2038, 2497

    scatterPlot(    path + PLOTS_DIR_NAME,
                    is_control,
                    rfp_normalized,
                    contours_rfp_vec,
                    rfp_contour_mask    );


    /** Classify the cell soma **/

    std::vector<std::vector<cv::Point>> contours_gfp, contours_rfp;
    cv::Mat gfp_intersection = cv::Mat::zeros(gfp_enhanced.size(), CV_8UC1);
    cv::Mat rfp_intersection = cv::Mat::zeros(rfp_enhanced_type1.size(), CV_8UC1);
    for (size_t i = 0; i < contours_dapi_filtered.size(); i++) {

        // Find DAPI-GFP Cell Soma
        std::vector<cv::Point> gfp_contour;
        cv::Mat temp;
        if (findCellSoma( contours_dapi_filtered[i], gfp_enhanced, &temp, &gfp_contour )) {
            contours_gfp.push_back(gfp_contour);
            bitwise_or(gfp_intersection, temp, gfp_intersection);
            cv::Mat temp_not;
            bitwise_not(temp, temp_not);
            bitwise_and(gfp_enhanced, temp_not, gfp_enhanced);
        }

        // Find DAPI-RFP Cell Soma
        std::vector<cv::Point> rfp_contour;
        if (findCellSoma( contours_dapi_filtered[i], rfp_enhanced_type1, &temp, &rfp_contour )) {
            contours_rfp.push_back(rfp_contour);
            bitwise_or(rfp_intersection, temp, rfp_intersection);
            cv::Mat temp_not;
            bitwise_not(temp, temp_not);
            bitwise_and(rfp_enhanced_type1, temp_not, rfp_enhanced_type1);
        }
    }


    /** Collect the metrics **/

    // Separation metrics for dapi-gfp cells
    float mean_dia = 0.0, stddev_dia = 0.0;
    float mean_aspect_ratio = 0.0, stddev_aspect_ratio = 0.0;
    float mean_error_ratio = 0.0, stddev_error_ratio = 0.0;
    separationMetrics(  contours_gfp, 
                        &mean_dia, 
                        &stddev_dia, 
                        &mean_aspect_ratio, 
                        &stddev_aspect_ratio, 
                        &mean_error_ratio, 
                        &stddev_error_ratio
                     );
    data_stream << contours_gfp.size() << "," 
                << mean_dia << "," 
                << stddev_dia << "," 
                << mean_aspect_ratio << "," 
                << stddev_aspect_ratio << "," 
                << mean_error_ratio << "," 
                << stddev_error_ratio << ",";

    // Separation metrics for dapi-rfp cells
    mean_dia = 0.0;
    stddev_dia = 0.0;
    mean_aspect_ratio = 0.0;
    stddev_aspect_ratio = 0.0;
    mean_error_ratio = 0.0;
    stddev_error_ratio = 0.0;
    separationMetrics(  contours_rfp, 
                        &mean_dia, 
                        &stddev_dia, 
                        &mean_aspect_ratio, 
                        &stddev_aspect_ratio, 
                        &mean_error_ratio, 
                        &stddev_error_ratio
                     );
    data_stream << contours_rfp.size() << "," 
                << mean_dia << "," 
                << stddev_dia << "," 
                << mean_aspect_ratio << "," 
                << stddev_aspect_ratio << "," 
                << mean_error_ratio << "," 
                << stddev_error_ratio << ",";


    /* Characterize the gfp channel */
    // Gfp low
    std::string gfp_low_output;
    binArea(gfp_low_contour_mask, gfp_low_contour_area, &gfp_low_output);
    data_stream << gfp_low_output << ",";

    // Gfp medium
    std::string gfp_medium_output;
    binArea(gfp_medium_contour_mask, gfp_medium_contour_area, &gfp_medium_output);
    data_stream << gfp_medium_output << ",";

    // Gfp high
    std::string gfp_high_output;
    binArea(gfp_high_contour_mask, gfp_high_contour_area, &gfp_high_output);
    data_stream << gfp_high_output << ",";


    // End of entry
    data_stream << std::endl;
    data_stream.close();


    /** Display the debug image **/

    if (DEBUG_FLAG) {
        // Initialize
        cv::Mat drawing_blue_debug = cv::Mat::zeros(dapi_enhanced.size(), CV_8UC1);
        //cv::Mat drawing_blue_debug  = 2*dapi_normalized;
        //cv::Mat drawing_green_debug = cv::Mat::zeros(gfp_enhanced.size(), CV_8UC1);
        cv::Mat drawing_green_debug = gfp_intersection;
        cv::Mat drawing_red_debug   = cv::Mat::zeros(rfp_enhanced_type1.size(), CV_8UC1);
        //cv::Mat drawing_red_debug = rfp_intersection;

        // Draw DAPI bondaries
        for (size_t i = 0; i < contours_dapi_filtered.size(); i++) {
            cv::Moments mu = moments(contours_dapi_filtered[i], true);
            cv::Point2f mc = cv::Point2f(   static_cast<float>(mu.m10/mu.m00), 
                                            static_cast<float>(mu.m01/mu.m00)   );
            cv::circle(drawing_blue_debug, mc, DAPI_MASK_RADIUS, 255, 1, 8);
            cv::circle(drawing_green_debug, mc, DAPI_MASK_RADIUS, 255, 1, 8);
            cv::circle(drawing_red_debug, mc, DAPI_MASK_RADIUS, 255, 1, 8);
        }

        // Merge the modified red, blue and green layers
        std::vector<cv::Mat> merge_debug;
        merge_debug.push_back(drawing_blue_debug);
        merge_debug.push_back(drawing_green_debug);
        merge_debug.push_back(drawing_red_debug);
        cv::Mat color_debug;
        cv::merge(merge_debug, color_debug);

        // Draw the debug image
        std::string out_debug = out_directory + analyzed_image_name;
        out_debug.insert(out_debug.find_last_of("."), "_debug", 6);
        cv::imwrite(out_debug.c_str(), color_debug);
    }


    /** Display the analyzed <dapi,gfp,rfp> image set **/

    // Initialize
    cv::Mat drawing_blue  = 2*dapi_normalized;
    cv::Mat drawing_green = gfp_normalized;
    cv::Mat drawing_red   = rfp_normalized;

    // Draw GFP bondaries
    for (size_t i = 0; i < contours_gfp.size(); i++) {
        //cv::RotatedRect min_ellipse = fitEllipse(cv::Mat(contours_gfp[i]));
        //ellipse(drawing_blue, min_ellipse, 255, 1, 8);
        //ellipse(drawing_green, min_ellipse, 255, 1, 8);
        //ellipse(drawing_red, min_ellipse, 0, 1, 8);
        drawContours(drawing_blue, contours_gfp, i, 255, 1, 8);
        drawContours(drawing_green, contours_gfp, i, 255, 1, 8);
        drawContours(drawing_red, contours_gfp, i, 0, 1, 8);
    }

    // Draw RFP bondaries
    for (size_t i = 0; i < contours_rfp.size(); i++) {
        //cv::RotatedRect min_ellipse = fitEllipse(cv::Mat(contours_rfp[i]));
        //ellipse(drawing_blue, min_ellipse, 255, 1, 8);
        //ellipse(drawing_green, min_ellipse, 0, 1, 8);
        //ellipse(drawing_red, min_ellipse, 255, 1, 8);
        drawContours(drawing_blue, contours_rfp, i, 255, 1, 8);
        drawContours(drawing_green, contours_rfp, i, 0, 1, 8);
        drawContours(drawing_red, contours_rfp, i, 255, 1, 8);
    }

    // Merge the modified red, blue and green layers
    std::vector<cv::Mat> merge_analyzed;
    merge_analyzed.push_back(drawing_blue);
    merge_analyzed.push_back(drawing_green);
    merge_analyzed.push_back(drawing_red);
    cv::Mat color_analyzed;
    cv::merge(merge_analyzed, color_analyzed);

    // Draw the analyzed image
    std::string out_analyzed = out_directory + analyzed_image_name;
    cv::imwrite(out_analyzed.c_str(), color_analyzed);


    return true;
}
Exemple #2
0
/* Process the images inside each directory */
bool processDir(std::string path, std::string image_name, std::string metrics_file) {

    /* Create the data output file for images that were processed */
    std::ofstream data_stream;
    data_stream.open(metrics_file, std::ios::app);
    if (!data_stream.is_open()) {
        std::cerr << "Could not open the data output file." << std::endl;
        return false;
    }

    // Create the output directory
    std::string out_directory = path + "result/";
    struct stat st = {0};
    if (stat(out_directory.c_str(), &st) == -1) {
        mkdir(out_directory.c_str(), 0700);
    }
    out_directory = out_directory + image_name + "/";
    st = {0};
    if (stat(out_directory.c_str(), &st) == -1) {
        mkdir(out_directory.c_str(), 0700);
    }

    // Count the number of images
    std::string dir_name = path + "jpg/" + image_name + "/";
    DIR *read_dir = opendir(dir_name.c_str());
    if (!read_dir) {
        std::cerr << "Could not open directory '" << dir_name << "'" << std::endl;
        return false;
    }
    struct dirent *dir = NULL;
    uint8_t z_count = 0;
    bool collect_name_pattern = false;
    std::string end_pattern;
    while ((dir = readdir(read_dir))) {
        if (!strcmp (dir->d_name, ".") || !strcmp (dir->d_name, "..")) continue;
        if (!collect_name_pattern) {
            std::string delimiter = "c1+";
            end_pattern = dir->d_name;
            size_t pos = end_pattern.find(delimiter);
            end_pattern.erase(0, pos);
            collect_name_pattern = true;
        }
        z_count++;
    }

    std::vector<cv::Mat>    blue_list(NUM_Z_LAYERS_COMBINED), 
                            green_list(NUM_Z_LAYERS_COMBINED), 
                            red_list(NUM_Z_LAYERS_COMBINED);
    for (uint8_t z_index = 1; z_index <= z_count; z_index++) {

        // Create the input filename and rgb stream output filenames
        std::string in_filename;
        if (z_count < 10) {
            in_filename = dir_name + image_name + 
                                        "_z" + std::to_string(z_index) + end_pattern;
        } else {
            if (z_index < 10) {
                in_filename = dir_name + image_name + 
                                        "_z0" + std::to_string(z_index) + end_pattern;
            } else if (z_index < 100) {
                in_filename = dir_name + image_name + 
                                        "_z" + std::to_string(z_index) + end_pattern;
            } else { // assuming number of z plane layers will never exceed 99
                std::cerr << "Does not support more than 99 z layers curently" << std::endl;
                return false;
            }
        }

        // Extract the bgr streams for each input image
        cv::Mat img = cv::imread(in_filename.c_str(), -1);
        if (img.empty()) return false;

        // Original image
        std::string out_original = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_a_original.jpg";
        if (DEBUG_FLAG) cv::imwrite(out_original.c_str(), img);

        std::vector<cv::Mat> channel(3);
        cv::split(img, channel);
        blue_list[(z_index-1)%NUM_Z_LAYERS_COMBINED]  = channel[0];
        green_list[(z_index-1)%NUM_Z_LAYERS_COMBINED] = channel[1];
        red_list[(z_index-1)%NUM_Z_LAYERS_COMBINED]   = channel[2];

        // Continue collecting layers if needed
        //if (z_index%NUM_Z_LAYERS_COMBINED && (z_index != z_count)) continue;
        if (z_index < NUM_Z_LAYERS_COMBINED) continue;

        data_stream << image_name << ","
                    << std::to_string(z_index - NUM_Z_LAYERS_COMBINED + 1) << ","
                    << std::to_string(z_index) << ",";

        // Merge some layers together
        cv::Mat blue  = cv::Mat::zeros(channel[0].size(), CV_8UC1);
        cv::Mat green = cv::Mat::zeros(channel[1].size(), CV_8UC1);
        cv::Mat red   = cv::Mat::zeros(channel[1].size(), CV_8UC1);
        for (unsigned int merge_index = 0; 
                    merge_index < NUM_Z_LAYERS_COMBINED; merge_index++) {
            bitwise_or(blue, blue_list[merge_index], blue);
            bitwise_or(green, green_list[merge_index], green);
            bitwise_or(red, red_list[merge_index], red);
        }

        /** Gather BGR channel information needed for feature extraction **/

        /* Enhance layers */

        // Red channel
        cv::Mat red_enhanced;
        if(!enhanceImage(red, ChannelType::RED, &red_enhanced)) return false;
        std::string out_red = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_red_enhanced.jpg";
        if (DEBUG_FLAG) cv::imwrite(out_red.c_str(), red_enhanced);

        // Purple channel
        cv::Mat purple_enhanced;
        if(!enhanceImage(red, ChannelType::PURPLE, &purple_enhanced)) return false;
        //cv::Mat red_enhanced_negative = cv::Mat::zeros(red_enhanced.size(), CV_8UC1);
        //bitwise_not(red_enhanced, red_enhanced_negative);
        //bitwise_and(purple_enhanced, red_enhanced_negative, purple_enhanced);
        std::string out_purple = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_purple_enhanced.jpg";
        if (DEBUG_FLAG) cv::imwrite(out_purple.c_str(), purple_enhanced);

        // Blue channel
        cv::Mat blue_enhanced;
        if(!enhanceImage(blue, ChannelType::BLUE, &blue_enhanced)) return false;
        //cv::Mat purple_enhanced_negative = cv::Mat::zeros(purple_enhanced.size(), CV_8UC1);
        //bitwise_not(purple_enhanced, purple_enhanced_negative);
        //bitwise_and(blue_enhanced, purple_enhanced_negative, blue_enhanced);
        std::string out_blue = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_blue_enhanced.jpg";
        if (DEBUG_FLAG) cv::imwrite(out_blue.c_str(), blue_enhanced);


        /* Segment */

        // Blue channel
        cv::Mat blue_segmented;
        std::vector<std::vector<cv::Point>> contours_blue;
        std::vector<cv::Vec4i> hierarchy_blue;
        std::vector<HierarchyType> blue_contour_mask;
        std::vector<double> blue_contour_area;
        contourCalc(    blue_enhanced,
                        MIN_NUCLEUS_SIZE,
                        &blue_segmented, 
                        &contours_blue,
                        &hierarchy_blue, 
                        &blue_contour_mask,
                        &blue_contour_area  );
        std::vector<std::vector<cv::Point>> contours_blue_filtered;
        filterCells(    ChannelType::BLUE, 
                        blue_enhanced, 
                        contours_blue, 
                        blue_contour_mask, 
                        &contours_blue_filtered );

        // Red channel
        cv::Mat red_segmented;
        std::vector<std::vector<cv::Point>> contours_red;
        std::vector<cv::Vec4i> hierarchy_red;
        std::vector<HierarchyType> red_contour_mask;
        std::vector<double> red_contour_area;
        contourCalc(    red_enhanced,
                        1.0,
                        &red_segmented, 
                        &contours_red,
                        &hierarchy_red, 
                        &red_contour_mask,
                        &red_contour_area  );


        /* Classify the cells */
        std::vector<std::vector<cv::Point>> contours_neural_soma;
        std::vector<std::vector<cv::Point>> contours_neural_nuclei, contours_astrocytes;
        cv::Mat purple_intersection = cv::Mat::zeros(purple_enhanced.size(), CV_8UC1);
        for (size_t i = 0; i < contours_blue_filtered.size(); i++) {
            std::vector<cv::Point> purple_contour;
            cv::Mat temp;
            if (findCellSoma( contours_blue_filtered[i], purple_enhanced, &temp, &purple_contour )) {
                contours_neural_soma.push_back(purple_contour);
                contours_neural_nuclei.push_back(contours_blue_filtered[i]);
                bitwise_or(purple_intersection, temp, purple_intersection);
                cv::Mat temp_not;
                bitwise_not(temp, temp_not);
                bitwise_and(purple_enhanced, temp_not, purple_enhanced);
            } else {
                contours_astrocytes.push_back(contours_blue_filtered[i]);
            }
        }


        /** Collect the metrics **/

        /* Cells */

        data_stream << contours_blue_filtered.size() << ",";

        float mean_dia = 0.0, stddev_dia = 0.0;
        float mean_aspect_ratio = 0.0, stddev_aspect_ratio = 0.0;
        float mean_error_ratio = 0.0, stddev_error_ratio = 0.0;

        // Characterize neural nuclei
        separationMetrics(  contours_neural_nuclei, 
                            &mean_dia, 
                            &stddev_dia, 
                            &mean_aspect_ratio, 
                            &stddev_aspect_ratio, 
                            &mean_error_ratio, 
                            &stddev_error_ratio
                        );
        data_stream << contours_neural_nuclei.size() << "," 
                    << mean_dia << "," 
                    << stddev_dia << "," 
                    << mean_aspect_ratio << "," 
                    << stddev_aspect_ratio << "," 
                    << mean_error_ratio << "," 
                    << stddev_error_ratio << ",";

        // Characterize the soma size
        separationMetrics(  contours_neural_soma, 
                            &mean_dia, 
                            &stddev_dia, 
                            &mean_aspect_ratio, 
                            &stddev_aspect_ratio, 
                            &mean_error_ratio, 
                            &stddev_error_ratio
                        );
        data_stream << mean_dia << "," 
                    << stddev_dia << "," 
                    << mean_aspect_ratio << "," 
                    << stddev_aspect_ratio << "," 
                    << mean_error_ratio << "," 
                    << stddev_error_ratio << ",";

        // Characterize the astrocyte nuclei
        separationMetrics(  contours_astrocytes, 
                            &mean_dia, 
                            &stddev_dia, 
                            &mean_aspect_ratio, 
                            &stddev_aspect_ratio, 
                            &mean_error_ratio, 
                            &stddev_error_ratio
                        );
        data_stream << contours_astrocytes.size() << "," 
                    << mean_dia << "," 
                    << stddev_dia << "," 
                    << mean_aspect_ratio << "," 
                    << stddev_aspect_ratio << "," 
                    << mean_error_ratio << "," 
                    << stddev_error_ratio << ",";


        /* Synapses */
        std::string red_output;
        binArea(red_contour_mask, red_contour_area, &red_output);
        data_stream << red_output << ",";

        data_stream << std::endl;


        /** Display analyzed images **/

        // Initialize
        cv::Mat drawing_blue  = blue;
        cv::Mat drawing_green = green;
        cv::Mat drawing_red   = red;

        // Draw soma
        for (size_t i = 0; i < contours_neural_soma.size(); i++) {
            drawContours(drawing_blue, contours_neural_soma, i, 255, 1, 8);
            drawContours(drawing_green, contours_neural_soma, i, 255, 1, 8);
            drawContours(drawing_red, contours_neural_soma, i, 255, 1, 8);
        }

        // Draw synapses
        for (size_t i = 0; i < contours_red.size(); i++) {
            drawContours(drawing_blue, contours_red, i, 0, 0, 8);
            drawContours(drawing_green, contours_red, i, 0, 0, 8);
            drawContours(drawing_red, contours_red, i, 255, -1, 8);
        }

        // Merge the modified red, blue and green layers
        std::vector<cv::Mat> merge_analyzed;
        merge_analyzed.push_back(drawing_blue);
        merge_analyzed.push_back(drawing_green);
        merge_analyzed.push_back(drawing_red);
        cv::Mat color_analyzed;
        cv::merge(merge_analyzed, color_analyzed);

        // Draw the analyzed image
        std::vector<int> compression_params;
        compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
        compression_params.push_back(101);
        cv::imwrite("/tmp/img.jpg", color_analyzed, compression_params);
        std::string out_analyzed = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_analyzed.tif";
        std::string cmd = "convert -quiet /tmp/img.jpg " + out_analyzed;
        system(cmd.c_str());
        system("rm /tmp/img.jpg");
    }
    closedir(read_dir);
    data_stream.close();

    return true;
}
/* Process the images inside each directory */
bool processDir(std::string path, std::string image_name, std::string metrics_file) {

    /* Create the data output file for images that were processed */
    std::ofstream data_stream;
    data_stream.open(metrics_file, std::ios::app);
    if (!data_stream.is_open()) {
        std::cerr << "Could not open the data output file." << std::endl;
        return false;
    }

    // Create the output directory
    std::string out_directory = path + "result/";
    struct stat st = {0};
    if (stat(out_directory.c_str(), &st) == -1) {
        mkdir(out_directory.c_str(), 0700);
    }
    out_directory = out_directory + image_name + "/";
    st = {0};
    if (stat(out_directory.c_str(), &st) == -1) {
        mkdir(out_directory.c_str(), 0700);
    }

    // Count the number of images
    std::string dir_name = path + "jpg/" + image_name + "/";
    DIR *read_dir = opendir(dir_name.c_str());
    if (!read_dir) {
        std::cerr << "Could not open directory '" << dir_name << "'" << std::endl;
        return false;
    }
    struct dirent *dir = NULL;
    uint8_t z_count = 0;
    bool collect_name_pattern = false;
    std::string end_pattern;
    while ((dir = readdir(read_dir))) {
        if (!strcmp (dir->d_name, ".") || !strcmp (dir->d_name, "..")) continue;
        if (!collect_name_pattern) {
            std::string delimiter = "c1+";
            end_pattern = dir->d_name;
            size_t pos = end_pattern.find(delimiter);
            end_pattern.erase(0, pos);
            collect_name_pattern = true;
        }
        z_count++;
    }

    std::vector<cv::Mat> blue_list(NUM_Z_LAYERS_COMBINED), green_list(NUM_Z_LAYERS_COMBINED);
    for (uint8_t z_index = 1; z_index <= z_count; z_index++) {

        // Create the input filename and rgb stream output filenames
        std::string in_filename;
        if (z_count < 10) {
            in_filename = dir_name + image_name + 
                                        "_z" + std::to_string(z_index) + end_pattern;
        } else {
            if (z_index < 10) {
                in_filename = dir_name + image_name + 
                                        "_z0" + std::to_string(z_index) + end_pattern;
            } else if (z_index < 100) {
                in_filename = dir_name + image_name + 
                                        "_z" + std::to_string(z_index) + end_pattern;
            } else { // assuming number of z plane layers will never exceed 99
                std::cerr << "Does not support more than 99 z layers curently" << std::endl;
                return false;
            }
        }

        // Extract the bgr streams for each input image
        cv::Mat img = cv::imread(in_filename.c_str(), -1);
        if (img.empty()) return false;

        // Original image
        std::string out_original = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_a_original.jpg";
        cv::imwrite(out_original.c_str(), img);

        std::vector<cv::Mat> channel(3);
        cv::split(img, channel);
        blue_list[(z_index-1)%NUM_Z_LAYERS_COMBINED]  = channel[0];
        green_list[(z_index-1)%NUM_Z_LAYERS_COMBINED] = channel[1];

        // Continue collecting layers if needed
        if (z_index%NUM_Z_LAYERS_COMBINED && (z_index != z_count)) continue;

        // Merge some layers together
        cv::Mat blue  = cv::Mat::zeros(channel[0].size(), CV_8UC1);
        cv::Mat green = cv::Mat::zeros(channel[1].size(), CV_8UC1);
        for (unsigned int merge_index = 0; 
                    merge_index < NUM_Z_LAYERS_COMBINED; merge_index++) {
            bitwise_or(blue, blue_list[merge_index], blue);
            bitwise_or(green, green_list[merge_index], green);
        }

        /** Gather BGR channel information needed for feature extraction **/

        // Blue channel
        std::string out_blue = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_blue.jpg";
        if (DEBUG_FLAG) cv::imwrite(out_blue.c_str(), blue);

        cv::Mat blue_enhanced;
        if(!enhanceImage(blue, ChannelType::BLUE, &blue_enhanced)) return false;
        out_blue.insert(out_blue.find_last_of("."), "_enhanced", 9);
        if (DEBUG_FLAG) cv::imwrite(out_blue.c_str(), blue_enhanced);

        cv::Mat blue_segmented;
        std::vector<std::vector<cv::Point>> contours_blue;
        std::vector<cv::Vec4i> hierarchy_blue;
        std::vector<HierarchyType> blue_contour_mask;
        std::vector<double> blue_contour_area;
        contourCalc(blue_enhanced, ChannelType::BLUE, 1.0, &blue_segmented, 
                &contours_blue, &hierarchy_blue, &blue_contour_mask, &blue_contour_area);

        // Green channel
        std::string out_green = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_green.jpg";
        if (DEBUG_FLAG) cv::imwrite(out_green.c_str(), green);

        cv::Mat green_enhanced;
        if(!enhanceImage(green, ChannelType::GREEN, &green_enhanced)) return false;
        out_green.insert(out_green.find_last_of("."), "_enhanced", 9);
        if (DEBUG_FLAG) cv::imwrite(out_green.c_str(), green_enhanced);

        cv::Mat not_blue, green_minus_blue, green_skeletonize;
        bitwise_not(blue_enhanced, not_blue);
        bitwise_and(green_enhanced, not_blue, green_minus_blue);
        skeletonize(green_enhanced, &green_skeletonize);
        out_green.insert(out_green.find_last_of("."), "_skeletonized", 13);
        if (DEBUG_FLAG) cv::imwrite(out_green.c_str(), green_skeletonize);

        cv::Mat green_segmented;
        std::vector<std::vector<cv::Point>> contours_green;
        std::vector<cv::Vec4i> hierarchy_green;
        std::vector<HierarchyType> green_contour_mask;
        std::vector<double> green_contour_area;
        contourCalc(green_enhanced, ChannelType::GREEN, 1.0, &green_segmented, 
                &contours_green, &hierarchy_green, &green_contour_mask, &green_contour_area);
    }
    closedir(read_dir);
    data_stream.close();

    return true;
}
Exemple #4
0
int main(int argc, char *argv[])
{
  image myPic;
  imageInfo picInfo;
  int count;
  char *outputType = NULL;
  int err;
  int aCrop = NO;
  int left = -1, right = -1, top = -1, bottom = -1;
  double xscale = 1, yscale = 1;
  double xs2, ys2;
  int xdim = 0, ydim = 0;
  int ditherMode = ' ';
  int mMono = NO;
  int outType = NO;
  int scaletofit = NO;
  int numBits = 1;
  char *outFile = NULL;
  char *type = NULL, *ext = NULL;
  char *p;
  int nv;
  double darken = 0;
  double contrast = 0;
  double rotate = 0;
  struct stat sbuf;
  int blend = NO;
  static char filename[MAXPATHLEN + 1] = "";
  int negative = NO;
  int enhance = NO;
  formatInfo fInfo;
  

  count = getargs(argc, argv, "nbosabLiRiTiBixdydXiYidcmbpbsbbiDdSbKdfseird",
		   &negative, &outputType, &aCrop, &left, &right, &top,
		   &bottom, &xscale, &yscale, &xdim, &ydim, &ditherMode,
		   &mMono, &outType, &scaletofit, &numBits, &darken,
		   &blend, &contrast, &outFile, &enhance, &rotate
		   );

  if (count < 0 || count == argc) {
    if (count < 0 && -count != '-')
      fprintf(stderr, "Bad flag: %c\n", -count);
    fprintf(stderr, "Usage: %s [-options] filename\n"
	     "  options:\n"
	     "\tn: make negative\n"
	     "\to: string indicating output format\n"
	     "\ta: auto crop non plotting areas\n"
	     "\tL, R, T, B: specify where to crop picture\n"
	     "\tx, y: specify scale factor in that direction\n"
	     "\tX, Y: specify dimension of picture in that direction\n"
	     "\td: select dither method: (D)ither, (T)hreshold, or (H)alftone\n"
	     "\tm: convert image to monochrome\n"
	     "\tp: dither image for output to printer\n"
	     "\ts: scale image to fill up specified screen\n"
	     "\tb: number of bits to dither to\n"
	     "\tD: how much to brighten image\n"
	     "\tK: contrast level\n"
	     "\tS: blend pixels together when scaling\n"
	     "\tf: file name to save to\n"
	     "\te: contrast for enhance image\n"
	     "\tr: number of degrees to rotate\n"
	     , *argv);
    exit(1);
  }

  for (; count < argc; count++) {
    if ((err = load_pic(argv[count], &myPic))) {
      fprintf(stderr, "Cannot load file %s\nError: %s\n", argv[count], picErrorStr(err));
      exit(1);
    }
    
    if (!getImageInfo(argv[count], &picInfo))
      type = picInfo.extension;

    if (!outputType) 
      outputType =  type;

    if (!infoForFormat(outputType, &fInfo)) {
      ext = fInfo.extension;
      if (scaletofit && !xdim && !ydim && fInfo.maxWidth && fInfo.maxHeight) {
	xdim = fInfo.maxWidth;
	ydim = fInfo.maxHeight;
      }
    }
    
    if (mMono)
      makeMono(&myPic);
    
    if (left >= 0 || right >= 0 || top >= 0 || bottom >= 0) {
      if (left < 0)
	left = 0;
      if (right < 0)
	right = myPic.width - 1;
      if (top < 0)
	top = 0;
      if (bottom < 0)
	bottom = myPic.height - 1;
      cropImage(left, top, right, bottom, &myPic);
    }
    
    if (aCrop)
      autoCropImage(&myPic, 40);

    if (rotate)
      rotateImage(&myPic, (rotate * -3.141592) / 180.0);
    
    xs2 = xscale;
    ys2 = yscale;
    if (scaletofit) {
      if (!ydim && xdim) {
	xs2 = (double) xdim / ((double) myPic.width * xscale) * xscale;
	ys2 = ((double) xdim / ((double) myPic.width * xscale)) * yscale;
      }
      else if (ydim) {
	xs2 = ((double) ydim / ((double) myPic.height * yscale)) * xscale;
	ys2 = (double) ydim / ((double) myPic.height * yscale) * yscale;
	if (xdim && (myPic.width * xs2) > xdim) {
	  xs2 = (double) xdim / ((double) myPic.width * xscale) * xscale;
	  ys2 = ((double) xdim / ((double) myPic.width * xscale)) * yscale;
	}
      }
    }
    else {
      if (xdim)
	xs2 = (double) xdim / (double) myPic.width;
      if (ydim)
	ys2 = (double) ydim / (double) myPic.height;
    }
    xscale = xs2;
    yscale = ys2;

    scaleImage(xscale, yscale, blend, &myPic);

    if (darken || contrast)
      adjustImage(&myPic, contrast, darken);
    if (enhance) {
      makeMono(&myPic);
      enhanceImage(&myPic, enhance);
    }
    
    handle_dithering(ditherMode, &myPic, outType, numBits);
    if (negative)
      negateImage(&myPic);

    if (outFile) {
      strcpy(filename, outFile);
      if (!stat(filename, &sbuf) && (sbuf.st_mode & S_IFDIR)) {
	if (filename[strlen(filename) - 1] != '/')
	  strcat(filename, "/");
	if ((p = strrchr(argv[count], '/')))
	  strcat(filename, p + 1);
	else
	  strcat(filename, argv[count]);
      }
    }
    else
      strcpy(filename, argv[count]);
    
    p = change_extension(filename, type, ext, 0);
    nv = 2;
    while (!stat(p, &sbuf)) {
      p = change_extension(filename, type, ext, nv);
      nv++;
    }

    if ((err = save_pic(p, outputType, &myPic))) {
      fprintf(stderr, "Cannot save file %s\nError: %s\n", p, picErrorStr(err));
      exit(1);
    }

    fprintf(stderr, "Saved %s as %s\n", argv[count], p);

    freeImage(&myPic);
  }

  exit(0);
  return 0;
}