deeplabv3-plus-pytorch icon indicating copy to clipboard operation
deeplabv3-plus-pytorch copied to clipboard

各位大佬们,谁能分享一下用C++写的后处理过程啊。

Open ZJDATY opened this issue 1 year ago • 10 comments

或者有没有C++后处理的开源的网址链接呢

ZJDATY avatar May 11 '23 08:05 ZJDATY

木有木有

bubbliiiing avatar May 11 '23 15:05 bubbliiiing

木有木有

@bubbliiiing 我从网上找了一堆后处理的代码,改改应该能用 ,可我改不出来。路过的大佬们 看看能不能改一改啊 例一,

const int num_classes = 1;

// 对每个像素进行后处理
void post_process(Mat& input_image, Mat& output_image, Mat& prob_map) {
	int height = input_image.rows;
	int width = input_image.cols;

	// 对每个像素进行遍历
	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			// 找到概率最大的类别
			int max_index = 0;
			float max_prob = 0.0;
			for (int k = 0; k < num_classes; k++) {
				float prob = prob_map.at<float>(i, j, k);//
				if (prob > max_prob) {
					max_index = k;
					max_prob = prob;
				}
			}

			// 将该像素的类别设置为概率最大的类别
			output_image.at<uchar>(i, j) = max_index;
		}
	}
}

例2:

const int OUTPUT_H = 512;
const int OUTPUT_W = 648;
const int NUM_CLASSES = 1;
void postprocess(const float* output, Mat& result)
{
	result.create(OUTPUT_H, OUTPUT_W, CV_8U);
	//result.create(OUTPUT_H, OUTPUT_W, CV_32SC1);
	for (int i = 0; i < OUTPUT_H; ++i) {
		for (int j = 0; j < OUTPUT_W; ++j) {
			int idx = i * OUTPUT_W + j;
			int max_idx = -1;
			float max_val = -FLT_MAX;
			for (int k = 0; k < NUM_CLASSES; ++k) {
				float val = output[idx * NUM_CLASSES + k];
				if (val > max_val) {
					max_val = val;
					max_idx = k;
				}
			}
			result.at<uint8_t>(i, j) = max_idx * 100;
			//result.at<int>(i, j) = max_idx * 100;
		}
	}
}

例三:

cv::Mat dnn_argmax(const Mat& score)
{
	const int rows = score.size[2];
	const int cols = score.size[3];
	const int chns = score.size[1];

	//存储argmax
	Mat maxCl = Mat::zeros(rows, cols, CV_8UC1);
	//存储max值
	Mat maxVal(rows, cols, CV_32FC1, score.data);
	//遍历每一个channel
	for (int ch = 1; ch < chns; ch++) {
		//遍历row 行
		for (int row = 0; row < rows; row++) {
			//--获取行指针加速内存操作
			const float* ptrScore = score.ptr<float>(0, ch, row);
			uint8_t* ptrMaxCl = maxCl.ptr<uint8_t>(row);
			float* ptrMaxVal = maxVal.ptr<float>(row);
			//遍历col 列
			for (int col = 0; col < cols; col++) {
				//一旦发现score中相应row,col位置的值大于maxVal,则更新maxCl和maxVal相应位置的值
				if (ptrScore[col] > ptrMaxVal[col]) {
					ptrMaxVal[col] = ptrScore[col];
					ptrMaxCl[col] = (uchar)ch;
				}
			}
		}
	}

	Mat seg2(rows, cols, CV_8UC1);//argmax结果
	for (int row = 0; row < rows; row++) {
		const uchar* ptrMaxCl = maxCl.ptr<uchar>(row);
		uchar* ptrSeg2 = seg2.ptr<uchar>(row);
		for (int col = 0; col < cols; col++) {
			ptrSeg2[col] = ptrMaxCl[col];
		}
	}
	return seg2;
}

ZJDATY avatar May 12 '23 06:05 ZJDATY

可以参考一下这个链接

DeepSpace98 avatar Aug 19 '23 01:08 DeepSpace98

可以参考一下这个链接

好的 好的 我周一研究一下

ZJDATY avatar Aug 19 '23 01:08 ZJDATY

可以参考一下我写的这个

// 获取模型输出数据的指针 // unsigned char* output_data = reinterpret_cast<unsigned char*>(outputs[output_index].buf); float* output_data = reinterpret_cast<float*>(outputs[0].buf); // 创建一个新的整数数组来存储解释后的数据 std::vector interpreted_data(output_size);

for (int i = 0; i < output_size/4; ++i) {
    
    interpreted_data[i] = output_data[i];
    // printf("%d,          %f\n",i,interpreted_data[i]);
}

int mini_h = nh/4;
int mini_w = nw/4;

float* pr = interpreted_data.data();
// printf("interpreted_data的大小:::::%d\n",interpreted_data.size());

int slice_start_h = (output_height - mini_h) / 2;
int slice_end_h = (output_height - mini_h) / 2 + mini_h;
int slice_start_w = (output_width - mini_w) / 2;
int slice_end_w = (output_width - mini_w) / 2 + mini_w;

// 计算切片后的数据大小
int sliced_height = slice_end_h - slice_start_h;
int sliced_width = slice_end_w - slice_start_w;
int sliced_channel = output_channel;
int sliced_size = sliced_height * sliced_width*sliced_channel;


// 创建一个新的数组来存储切片后的数据
std::vector<float> sliced_data(sliced_size);
// 复制数据到新数组
for (int k = 0;k<sliced_channel;k++){
  for (int i = slice_start_h; i < slice_end_h; i++) {
    for (int j = slice_start_w; j < slice_end_w; j++) {
        int src_index =k*output_height*output_width+ i * output_width + j;
        int dst_index = k*sliced_height*sliced_width + (i - slice_start_h) * sliced_width + (j - slice_start_w);
        sliced_data[dst_index] = pr[src_index];
    }
  }
}
pr = sliced_data.data();

// softmax操作
softmax(pr, sliced_channel, sliced_height,sliced_width);


cv::Mat segmented_img = cv::Mat(mini_h, mini_w, CV_8UC3);
std::vector<int> argmax_indices; // 存储 argmax 结果
for (int h = 0; h < sliced_height; ++h) {
    for (int w = 0; w < sliced_width; ++w) {
        int max_index = 0;
        float max_value = pr[h * sliced_width + w];

        for (int c = 1; c < output_channel; ++c) {
            float current_value = pr[c*sliced_height*sliced_width+ h * sliced_width + w];
            if (current_value > max_value) {
                max_value = current_value;
                max_index = c;
            }
        }

        argmax_indices.push_back(max_index);
        // printf("%d ",max_index);

        segmented_img.at<cv::Vec3b>(h, w) = cv::Vec3b(colors[max_index][2], colors[max_index][1], colors[max_index][0]);
    }
    // printf("\n");
}
printf("argmax_indices大小::%d\n",argmax_indices.size());




// cv::Mat segmented_img = cv::Mat(mini_h, mini_w, CV_8UC3);
// // Map argmax_indices to colors and fill the segmented image(可优化可以直接生成mat数据)
// for (int h = 0; h < mini_h; ++h) {
//     for (int w = 0; w < mini_w; ++w) {
//         int index = argmax_indices[h * mini_w + w];
//         segmented_img.at<cv::Vec3b>(h, w) = cv::Vec3b(colors[index][2], colors[index][1], colors[index][0]);
//     }
// }




gettimeofday(&stop_time, NULL);
printf("后处理时间::once run use %f ms\n", (__get_us(stop_time) - __get_us(start_time)) / 1000);

bool saved = cv::imwrite(save_path, segmented_img);
if(saved){
  std::cout<<"图片已存为:"<<save_path<<"\n\n\n\n"<<std::endl;

}

xiaozggggg avatar Aug 24 '23 12:08 xiaozggggg

@xiaozggggg 好的 多谢 我明天研究一下

ZJDATY avatar Aug 24 '23 12:08 ZJDATY

@ZJDATY 有写出来吗?分享一下?

Huangyouling avatar Dec 19 '23 11:12 Huangyouling

@ZJDATY 有写出来吗?分享一下?

上面 大佬们 不是都给出来了吗

ZJDATY avatar Dec 21 '23 07:12 ZJDATY

@ZJDATY xiaozggggg这个大佬的吗?你自己有实现吗?我的输出是1 * 21 * 513 * 513,下面是我推理的代码,后处理没明白,能看看不?auto input = engine->input(0); auto output = engine->tensor("output"); auto stream = engine->get_stream();

int network_width = 513;
int network_height = 513;

int image_width = rgb_image.cols;
int image_height = rgb_image.rows;

float scale = std::min(
    network_width / (float)image_width,
    network_height / (float)image_height
);

float affine_matrix_array[] = {
    scale, 0, 0,
    0, scale, 0
};

cv::Mat affine_matrix(2, 3, CV_32F, affine_matrix_array);
cv::Mat inverse_matrix;
cv::invertAffineTransform(affine_matrix, inverse_matrix);

float mean[3] = {0.485, 0.456, 0.406};
float std[3] = {0.229, 0.224, 0.225};
float* mean_ptr = nullptr;
float* std_ptr = nullptr;
float* device_inverse_matrix = nullptr;

cudaMalloc(&device_inverse_matrix, 6 * sizeof(float));
cudaMemcpyAsync(device_inverse_matrix, inverse_matrix.data, 6 * sizeof(float), cudaMemcpyHostToDevice, stream);

cudaMalloc(&mean_ptr, 3 * sizeof(float));
cudaMemcpyAsync(mean_ptr, mean, 3 * sizeof(float), cudaMemcpyHostToDevice, stream);

cudaMalloc(&std_ptr, 3 * sizeof(float));
cudaMemcpyAsync(std_ptr, std, 3 * sizeof(float), cudaMemcpyHostToDevice, stream);
auto start_time = std::chrono::high_resolution_clock::now();
cvtcolor_and_nomalize_gpu(
    0,
    rgb_image,
    input,
    device_inverse_matrix,
    mean_ptr, std_ptr
);

engine->forward();
auto end_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
std::cout << "Inference time: " << duration.count() << " ms" << std::endl;
float* outputdata = output->cpu<float>();

Huangyouling avatar Dec 21 '23 07:12 Huangyouling

好了我也自己实现了。 int height = 513; int width = 513; int num_classes = 21; cv::Mat mask(height, width, CV_8UC3); // 用于彩色mask的3通道颜色图像

for (int h = 0; h < height; h++) {
    for (int w = 0; w < width; w++) {
        int max_index = 0;
        float max_prob = resultBuffer[h * width + w];

        for (int c = 1; c < num_classes; c++) {
            float prob = resultBuffer[c * height * width + h * width + w];
            if (prob > max_prob) {
                max_prob = prob;
                max_index = c;
            }
        }

        // 根据max_index分配颜色
        cv::Vec3b color = GetColorForClass(max_index); // 实现这个函数,基于你的类别-颜色映射
        mask.at<cv::Vec3b>(cv::Point(w, h)) = color;
    }
}

// 保存mask
cv::imwrite("segmentation_mask.png", mask);

Huangyouling avatar Dec 21 '23 08:12 Huangyouling