SGProcessingManager/src/processors/processing_processor_mnn_image.cpp¶
Namespaces¶
| Name |
|---|
| sgns |
| sgns::sgprocessing |
Source code¶
#include "processors/processing_processor_mnn_image.hpp"
#include "datasplitter/ImageSplitter.hpp"
#include <functional>
#include <thread>
#include <openssl/sha.h> // For SHA256_DIGEST_LENGTH
#include "util/sha256.hpp"
#include "util/InputTypes.hpp"
//#define STB_IMAGE_IMPLEMENTATION
//#define STB_IMAGE_WRITE_IMPLEMENTATION
//#include "stb_image.h"
//#include "stb_image_write.h"
namespace sgns::sgprocessing
{
using namespace MNN;
std::vector<uint8_t> MNN_Image::StartProcessing( std::vector<std::vector<uint8_t>> &chunkhashes,
const sgns::IoDeclaration &proc,
std::vector<char> &imageData,
std::vector<char> &modelFile )
{
std::vector<uint8_t> modelFile_bytes;
modelFile_bytes.assign(modelFile.begin(), modelFile.end());
//Get stride data
std::vector<uint8_t> subTaskResultHash(SHA256_DIGEST_LENGTH);
auto block_len = proc.get_dimensions().value().get_block_len().value();
auto block_line_stride = proc.get_dimensions().value().get_block_line_stride().value();
auto block_stride = proc.get_dimensions().value().get_block_stride().value();
auto chunk_line_stride = proc.get_dimensions().value().get_chunk_line_stride().value();
auto chunk_offset = proc.get_dimensions().value().get_chunk_offset().value();
auto chunk_stride = proc.get_dimensions().value().get_chunk_stride().value();
auto chunk_subchunk_height = proc.get_dimensions().value().get_chunk_subchunk_height().value();
auto chunk_subchunk_width = proc.get_dimensions().value().get_chunk_subchunk_width().value();
auto chunk_count = proc.get_dimensions().value().get_chunk_count().value();
auto format = proc.get_format().value();
//Make sure channels is valid.
auto maybe_channels = sgns::sgprocessing::InputTypes::GetImageChannels( proc.get_format().value() );
m_logger->debug( "Channels to process {}", maybe_channels.value() );
if ( !maybe_channels )
{
return std::vector<uint8_t>();
}
auto channels = maybe_channels.value();
//for ( auto image : *imageData_ )
//{
std::vector<uint8_t> output(imageData.size());
std::transform(imageData.begin(), imageData.end(), output.begin(),
[]( char c ) { return static_cast<uint8_t>( c ); } );
//ImageSplitter animageSplit( output, task.block_line_stride(), task.block_stride(), task.block_len() );
ImageSplitter animageSplit(output, block_line_stride, block_stride, block_len, channels);
auto dataindex = 0;
ImageSplitter ChunkSplit( animageSplit.GetPart( dataindex ), chunk_line_stride, chunk_stride,
animageSplit.GetPartHeightActual( dataindex ) / chunk_subchunk_height *
chunk_line_stride, channels);
auto totalChunks = proc.get_dimensions().value().get_chunk_count().value();
m_progress = 0.0f; // Reset progress at start
for ( int chunkIdx = 0; chunkIdx < totalChunks; ++chunkIdx )
{
m_logger->info( "Chunk IDX {} Total {}",
chunkIdx,
totalChunks );
std::vector<uint8_t> shahash( SHA256_DIGEST_LENGTH );
// Chunk result hash should be calculated
size_t chunkHash = 0;
auto procresults =
Process( ChunkSplit.GetPart( chunkIdx ), modelFile_bytes, channels, ChunkSplit.GetPartWidthActual( chunkIdx ),
ChunkSplit.GetPartHeightActual( chunkIdx ) );
const float *data = procresults->host<float>();
size_t dataSize = procresults->elementSize() * sizeof( float );
shahash = sgprocmanagersha::sha256( data, dataSize );
std::string hashString( shahash.begin(), shahash.end() );
chunkhashes.push_back( shahash );
std::string combinedHash = std::string(subTaskResultHash.begin(), subTaskResultHash.end()) + hashString;
subTaskResultHash = sgprocmanagersha::sha256( combinedHash.c_str(), combinedHash.length() );
// Update progress: round to 2 decimal places
m_progress = std::round(((chunkIdx + 1) * 100.0f / totalChunks) * 100.0f) / 100.0f;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return subTaskResultHash;
//}
//return subTaskResultHash;
}
std::unique_ptr<MNN::Tensor> MNN_Image::Process(const std::vector<uint8_t>& imgdata,
std::vector<uint8_t>& modelFile,
const int channels,
const int origwidth,
const int origheight,
const std::string filename)
{
std::vector<uint8_t> ret_vect(imgdata);
// Get Target Width
const int targetWidth = static_cast<int>((float)origwidth / (float)OUTPUT_STRIDE) * OUTPUT_STRIDE + 1;
const int targetHeight = static_cast<int>((float)origheight / (float)OUTPUT_STRIDE) * OUTPUT_STRIDE + 1;
// Scale
CV::Point scale;
scale.fX = (float)origwidth / (float)targetWidth;
scale.fY = (float)origheight / (float)targetHeight;
// Create net and session
const void* buffer = static_cast<const void*>( modelFile.data() );
auto mnnNet = std::shared_ptr<MNN::Interpreter>( MNN::Interpreter::createFromBuffer( buffer, modelFile.size() ) );
//auto backendConfig = new MNN::BackendConfig();
//backendConfig->power = MNN::BackendConfig::Power_Low;
//backendConfig->queuePriority = 0.1f;
MNN::ScheduleConfig netConfig;
netConfig.type = MNN_FORWARD_VULKAN;
netConfig.numThread = 4;
netConfig.mode = 0;
//netConfig.backendConfig = backendConfig;
auto session = mnnNet->createSession( netConfig );
auto input = mnnNet->getSessionInput( session, nullptr );
if ( input->elementSize() <= 4 )
{
mnnNet->resizeTensor( input, { 1, 3, targetHeight, targetWidth } );
mnnNet->resizeSession( session );
}
// Preprocess input image
{
const float means[3] = { 127.5f, 127.5f, 127.5f };
const float norms[3] = { 2.0f / 255.0f, 2.0f / 255.0f, 2.0f / 255.0f };
CV::ImageProcess::Config preProcessConfig;
::memcpy( preProcessConfig.mean, means, sizeof( means ) );
::memcpy( preProcessConfig.normal, norms, sizeof( norms ) );
preProcessConfig.sourceFormat = CV::RGBA;
if (channels == 3)
{
preProcessConfig.sourceFormat = CV::RGB;
}
preProcessConfig.destFormat = CV::RGB;
preProcessConfig.filterType = CV::BILINEAR;
auto pretreat = std::shared_ptr<CV::ImageProcess>( CV::ImageProcess::create( preProcessConfig ) );
CV::Matrix trans;
// Dst -> [0, 1]
trans.postScale( 1.0 / targetWidth, 1.0 / targetHeight );
//[0, 1] -> Src
trans.postScale( origwidth, origheight );
pretreat->setMatrix( trans );
pretreat->convert( ret_vect.data(), origwidth, origheight, 0, input );
}
// Log preprocessed input tensor data hash
{
const float *inputData = input->host<float>();
size_t inputDataSize = input->elementSize() * sizeof( float );
}
{
AUTOTIME;
mnnNet->runSession( session );
}
auto outputTensor = mnnNet->getSessionOutput( session, nullptr );
auto outputHost = std::make_unique<MNN::Tensor>( outputTensor, MNN::Tensor::CAFFE );
outputTensor->copyToHostTensor( outputHost.get() );
return outputHost;
}
}
Updated on 2026-03-04 at 13:10:44 -0800