Mercurial > hg > orthanc-stone
comparison RenderingPlugin/Sources/Plugin.cpp @ 1888:9bdce2c91620
start rendering rt-struct
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 17 Jan 2022 21:20:56 +0100 |
parents | aa4ed1cf4e8d |
children | fe4befc9c2b0 |
comparison
equal
deleted
inserted
replaced
1887:aa4ed1cf4e8d | 1888:9bdce2c91620 |
---|---|
405 { | 405 { |
406 std::unique_ptr<Orthanc::ImageAccessor> target(ApplyUnchecked(source)); | 406 std::unique_ptr<Orthanc::ImageAccessor> target(ApplyUnchecked(source)); |
407 | 407 |
408 const unsigned int h = target->GetHeight(); | 408 const unsigned int h = target->GetHeight(); |
409 const unsigned int w = target->GetWidth(); | 409 const unsigned int w = target->GetWidth(); |
410 | 410 |
411 // Apply thresholding to get back a binary image | |
411 for (unsigned int y = 0; y < h; y++) | 412 for (unsigned int y = 0; y < h; y++) |
412 { | 413 { |
413 uint8_t* p = reinterpret_cast<uint8_t*>(target->GetRow(y)); | 414 uint8_t* p = reinterpret_cast<uint8_t*>(target->GetRow(y)); |
414 for (unsigned int x = 0; x < w; x++, p++) | 415 for (unsigned int x = 0; x < w; x++, p++) |
415 { | 416 { |
428 } | 429 } |
429 } | 430 } |
430 }; | 431 }; |
431 | 432 |
432 | 433 |
434 static OrthancStone::DicomInstanceParameters* GetInstanceParameters(const std::string& orthancId) | |
435 { | |
436 OrthancPlugins::MemoryBuffer tags; | |
437 if (!tags.RestApiGet("/instances/" + orthancId + "/tags", false)) | |
438 { | |
439 throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem); | |
440 } | |
441 | |
442 Json::Value json; | |
443 tags.ToJson(json); | |
444 | |
445 Orthanc::DicomMap m; | |
446 m.FromDicomAsJson(json); | |
447 | |
448 return new OrthancStone::DicomInstanceParameters(m); | |
449 } | |
450 | |
451 | |
452 static void AnswerNumpyImage(OrthancPluginRestOutput* output, | |
453 const Orthanc::ImageAccessor& image, | |
454 bool compress) | |
455 { | |
456 std::string answer; | |
457 Orthanc::NumpyWriter writer; | |
458 writer.SetCompressed(compress); | |
459 Orthanc::IImageWriter::WriteToMemory(writer, answer, image); | |
460 | |
461 OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, | |
462 answer.c_str(), answer.size(), "application/octet-stream"); | |
463 } | |
464 | |
465 | |
433 static void RenderNumpyFrame(OrthancPluginRestOutput* output, | 466 static void RenderNumpyFrame(OrthancPluginRestOutput* output, |
434 const char* url, | 467 const char* url, |
435 const OrthancPluginHttpRequest* request) | 468 const OrthancPluginHttpRequest* request) |
436 { | 469 { |
437 DataAugmentationParameters dataAugmentation; | 470 DataAugmentationParameters dataAugmentation; |
452 { | 485 { |
453 LOG(WARNING) << "Unsupported option for data augmentation: " << key; | 486 LOG(WARNING) << "Unsupported option for data augmentation: " << key; |
454 } | 487 } |
455 } | 488 } |
456 } | 489 } |
457 | 490 |
458 OrthancPlugins::MemoryBuffer tags; | 491 std::unique_ptr<OrthancStone::DicomInstanceParameters> parameters(GetInstanceParameters(request->groups[0])); |
459 if (!tags.RestApiGet("/instances/" + std::string(request->groups[0]) + "/tags", false)) | |
460 { | |
461 throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem); | |
462 } | |
463 | |
464 Json::Value json; | |
465 tags.ToJson(json); | |
466 | |
467 Orthanc::DicomMap m; | |
468 m.FromDicomAsJson(json); | |
469 | |
470 OrthancStone::DicomInstanceParameters parameters(m); | |
471 | 492 |
472 OrthancPlugins::MemoryBuffer dicom; | 493 OrthancPlugins::MemoryBuffer dicom; |
473 dicom.GetDicomInstance(request->groups[0]); | 494 dicom.GetDicomInstance(request->groups[0]); |
474 | 495 |
475 unsigned int frame = boost::lexical_cast<unsigned int>(request->groups[1]); | 496 unsigned int frame = boost::lexical_cast<unsigned int>(request->groups[1]); |
481 source.AssignReadOnly(Convert(image.GetPixelFormat()), image.GetWidth(), image.GetHeight(), | 502 source.AssignReadOnly(Convert(image.GetPixelFormat()), image.GetWidth(), image.GetHeight(), |
482 image.GetPitch(), image.GetBuffer()); | 503 image.GetPitch(), image.GetBuffer()); |
483 | 504 |
484 std::unique_ptr<Orthanc::ImageAccessor> modified; | 505 std::unique_ptr<Orthanc::ImageAccessor> modified; |
485 | 506 |
486 if (parameters.GetSopClassUid() == OrthancStone::SopClassUid_DicomSeg) | 507 if (parameters->GetSopClassUid() == OrthancStone::SopClassUid_DicomSeg) |
487 { | 508 { |
488 modified.reset(dataAugmentation.ApplyBinaryMask(source)); | 509 modified.reset(dataAugmentation.ApplyBinaryMask(source)); |
489 } | 510 } |
490 else if (source.GetFormat() == Orthanc::PixelFormat_RGB24) | 511 else if (source.GetFormat() == Orthanc::PixelFormat_RGB24) |
491 { | 512 { |
492 modified.reset(dataAugmentation.Apply(source)); | 513 modified.reset(dataAugmentation.Apply(source)); |
493 } | 514 } |
494 else | 515 else |
495 { | 516 { |
496 std::unique_ptr<Orthanc::ImageAccessor> converted(parameters.ConvertToFloat(source)); | 517 std::unique_ptr<Orthanc::ImageAccessor> converted(parameters->ConvertToFloat(source)); |
497 assert(converted.get() != NULL); | 518 assert(converted.get() != NULL); |
498 | 519 |
499 modified.reset(dataAugmentation.Apply(*converted)); | 520 modified.reset(dataAugmentation.Apply(*converted)); |
500 } | 521 } |
501 | 522 |
502 assert(modified.get() != NULL); | 523 assert(modified.get() != NULL); |
503 | 524 AnswerNumpyImage(output, *modified, compress); |
504 std::string answer; | |
505 Orthanc::NumpyWriter writer; | |
506 writer.SetCompressed(compress); | |
507 Orthanc::IImageWriter::WriteToMemory(writer, answer, *modified); | |
508 | |
509 OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, | |
510 answer.c_str(), answer.size(), "application/octet-stream"); | |
511 } | 525 } |
512 | 526 |
513 | 527 |
514 static bool IsRtStruct(const std::string& instanceId) | 528 static bool IsRtStruct(const std::string& instanceId) |
515 { | 529 { |
637 std::string s = answer.toStyledString(); | 651 std::string s = answer.toStyledString(); |
638 OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, s.c_str(), s.size(), "application/json"); | 652 OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, s.c_str(), s.size(), "application/json"); |
639 } | 653 } |
640 | 654 |
641 | 655 |
656 | |
642 static void RenderRtStruct(OrthancPluginRestOutput* output, | 657 static void RenderRtStruct(OrthancPluginRestOutput* output, |
643 const char* url, | 658 const char* url, |
644 const OrthancPluginHttpRequest* request) | 659 const OrthancPluginHttpRequest* request) |
645 { | 660 { |
646 static const char* MAIN_DICOM_TAGS = "MainDicomTags"; | |
647 | |
648 DicomStructureCache::Accessor accessor(DicomStructureCache::GetSingleton(), request->groups[0]); | 661 DicomStructureCache::Accessor accessor(DicomStructureCache::GetSingleton(), request->groups[0]); |
649 | 662 |
650 if (!accessor.IsValid()) | 663 if (!accessor.IsValid()) |
651 { | 664 { |
652 throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem); | 665 throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem); |
683 if (instanceId.empty()) | 696 if (instanceId.empty()) |
684 { | 697 { |
685 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, | 698 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, |
686 "Missing option \"instance\" to provide the Orthanc identifier of the instance of interest"); | 699 "Missing option \"instance\" to provide the Orthanc identifier of the instance of interest"); |
687 } | 700 } |
701 | |
702 std::unique_ptr<OrthancStone::DicomInstanceParameters> parameters(GetInstanceParameters(instanceId)); | |
688 | 703 |
689 size_t structureIndex; | 704 size_t structureIndex; |
690 bool found = false; | 705 bool found = false; |
691 for (size_t i = 0; i < accessor.GetRtStruct().GetStructuresCount(); i++) | 706 for (size_t i = 0; i < accessor.GetRtStruct().GetStructuresCount(); i++) |
692 { | 707 { |
702 { | 717 { |
703 throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, | 718 throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, |
704 "Unknown structure name: " + structureName); | 719 "Unknown structure name: " + structureName); |
705 } | 720 } |
706 | 721 |
707 Json::Value instance; | 722 std::list< std::vector<OrthancStone::Vector> > polygons; |
708 if (!OrthancPlugins::RestApiGet(instance, "/instances/" + instanceId, false)) | 723 accessor.GetRtStruct().GetStructurePoints(polygons, structureIndex, parameters->GetSopInstanceUid()); |
709 { | 724 |
710 throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, | 725 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, parameters->GetWidth(), parameters->GetHeight(), false); |
711 "Unknown instance with Orthanc ID: " + instanceId); | 726 Orthanc::ImageProcessing::Set(tmp, 0); |
712 } | 727 |
713 | |
714 if (instance.type() != Json::objectValue || | |
715 !instance.isMember(MAIN_DICOM_TAGS) || | |
716 instance[MAIN_DICOM_TAGS].type() != Json::objectValue) | |
717 { | |
718 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
719 } | |
720 | |
721 std::string sopInstanceUid = Orthanc::SerializationToolbox::ReadString(instance[MAIN_DICOM_TAGS], "SOPInstanceUID"); | |
722 | |
723 | |
724 std::list< std::vector<OrthancStone::Vector> > p; | |
725 accessor.GetRtStruct().GetStructurePoints(p, structureIndex, sopInstanceUid); | |
726 | |
727 // curl 'http://localhost:8042/stone/rt-struct/54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9/numpy?structure=BODY&instance=0dd13003-9b1b2712-0fb44325-48c28c99-430d111b' | |
728 unsigned int count = 0; | |
729 for (std::list< std::vector<OrthancStone::Vector> >::const_iterator | 728 for (std::list< std::vector<OrthancStone::Vector> >::const_iterator |
730 it = p.begin(); it != p.end(); ++it) | 729 it = polygons.begin(); it != polygons.end(); ++it) |
731 { | 730 { |
732 printf("%d: ", count++); | 731 std::vector<Orthanc::ImageProcessing::ImagePoint> points; |
732 points.reserve(it->size()); | |
733 | |
733 for (size_t i = 0; i < it->size(); i++) | 734 for (size_t i = 0; i < it->size(); i++) |
734 { | 735 { |
735 printf("(%.1f,%.1f,%.1f) ", (*it)[i][0], (*it)[i][1], (*it)[i][2]); | 736 double x, y; |
736 } | 737 parameters->GetGeometry().ProjectPoint(x, y, (*it) [i]); |
737 printf("\n"); | 738 points.push_back(Orthanc::ImageProcessing::ImagePoint(x, y)); |
738 } | 739 } |
739 | 740 |
740 std::string s = "hello"; | 741 Orthanc::ImageProcessing::FillPolygon(tmp, points, 255); |
741 OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, s.c_str(), s.size(), "application/json"); | 742 } |
743 | |
744 AnswerNumpyImage(output, tmp, true); | |
742 } | 745 } |
743 | 746 |
744 | 747 |
745 OrthancPluginErrorCode OnChangeCallback(OrthancPluginChangeType changeType, | 748 OrthancPluginErrorCode OnChangeCallback(OrthancPluginChangeType changeType, |
746 OrthancPluginResourceType resourceType, | 749 OrthancPluginResourceType resourceType, |