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,