comparison OrthancStone/Sources/Scene2D/AnnotationsSceneLayer.cpp @ 1984:187a261d7ae2

computation of mean and stddev in rectangle probes
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 31 Oct 2022 14:42:46 +0100
parents 20fa913272b7
children bb307007f8e2
comparison
equal deleted inserted replaced
1983:20fa913272b7 1984:187a261d7ae2
1522 Segment& segment2_; 1522 Segment& segment2_;
1523 Segment& segment3_; 1523 Segment& segment3_;
1524 Segment& segment4_; 1524 Segment& segment4_;
1525 Text& label_; 1525 Text& label_;
1526 1526
1527 void UpdateLabel() 1527 protected:
1528 { 1528 virtual void UpdateProbeForLayer(const ISceneLayer& layer) ORTHANC_OVERRIDE
1529 TextSceneLayer content; 1529 {
1530 1530 double x1 = handle1_.GetCenter().GetX();
1531 const double x1 = handle1_.GetCenter().GetX(); 1531 double y1 = handle1_.GetCenter().GetY();
1532 const double y1 = handle1_.GetCenter().GetY(); 1532 double x2 = handle2_.GetCenter().GetX();
1533 const double x2 = handle2_.GetCenter().GetX(); 1533 double y2 = handle2_.GetCenter().GetY();
1534 const double y2 = handle2_.GetCenter().GetY();
1535 1534
1536 // Put the label to the right of the right-most handle 1535 // Put the label to the right of the right-most handle
1537 //const double y = std::min(y1, y2); 1536 //const double y = std::min(y1, y2);
1538 const double y = (y1 + y2) / 2.0; 1537 const double y = (y1 + y2) / 2.0;
1539 if (x1 < x2) 1538 if (x1 < x2)
1540 { 1539 {
1541 content.SetPosition(x2, y); 1540 label_.SetPosition(x2, y);
1542 } 1541 }
1543 else 1542 else
1544 { 1543 {
1545 content.SetPosition(x1, y); 1544 label_.SetPosition(x1, y);
1546 } 1545 }
1547 1546
1548 content.SetAnchor(BitmapAnchor_CenterLeft); 1547 std::string text;
1549 content.SetBorder(10); 1548
1550
1551 const double area = std::abs(x1 - x2) * std::abs(y1 - y2);
1552
1553 char buf[32]; 1549 char buf[32];
1554 1550
1555 switch (GetUnits()) 1551 if (GetUnits() == Units_Millimeters)
1556 { 1552 {
1557 case Units_Millimeters: 1553 const double area = std::abs(x1 - x2) * std::abs(y1 - y2);
1558 sprintf(buf, "%0.2f cm%c%c", 1554
1559 area / 100.0, 1555 sprintf(buf, "%0.2f cm%c%c",
1560 0xc2, 0xb2 /* two bytes corresponding to two power in UTF-8 */); 1556 area / 100.0,
1561 break; 1557 0xc2, 0xb2 /* two bytes corresponding to two power in UTF-8 */);
1562 1558 text = buf;
1563 case Units_Pixels: 1559 }
1564 // Don't report area (pixel-times-pixel is a strange unit) 1560
1565 sprintf(buf, "hello"); 1561 if (layer.GetType() == ISceneLayer::Type_FloatTexture)
1566 break; 1562 {
1563 const TextureBaseSceneLayer& texture = dynamic_cast<const TextureBaseSceneLayer&>(layer);
1564 const AffineTransform2D sceneToTexture = AffineTransform2D::Invert(texture.GetTransform());
1565
1566 const Orthanc::ImageAccessor& image = texture.GetTexture();
1567 assert(image.GetFormat() == Orthanc::PixelFormat_Float32);
1568
1569 sceneToTexture.Apply(x1, y1);
1570 sceneToTexture.Apply(x2, y2);
1571 int ix1 = static_cast<int>(std::floor(x1));
1572 int iy1 = static_cast<int>(std::floor(y1));
1573 int ix2 = static_cast<int>(std::floor(x2));
1574 int iy2 = static_cast<int>(std::floor(y2));
1575
1576 if (ix1 > ix2)
1577 {
1578 std::swap(ix1, ix2);
1579 }
1580
1581 if (iy1 > iy2)
1582 {
1583 std::swap(iy1, iy2);
1584 }
1585
1586 LinearAlgebra::OnlineVarianceEstimator estimator;
1587
1588 for (int y = std::max(0, iy1); y <= std::min(static_cast<int>(image.GetHeight()) - 1, iy2); y++)
1589 {
1590 int x = std::max(0, ix1);
1567 1591
1568 default: 1592 const float* p = reinterpret_cast<const float*>(image.GetConstRow(y)) + x;
1569 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 1593
1570 } 1594 for (; x <= std::min(static_cast<int>(image.GetWidth()) - 1, ix2); x++, p++)
1571 1595 {
1572 content.SetText(buf); 1596 estimator.AddSample(*p);
1573 1597 }
1574 label_.SetContent(content); 1598 }
1575 } 1599
1576 1600 if (estimator.GetCount() > 0)
1577 protected: 1601 {
1578 virtual void UpdateProbeForLayer(const ISceneLayer& layer) ORTHANC_OVERRIDE 1602 if (!text.empty())
1579 { 1603 {
1580 // TODO 1604 text += "\n";
1605 }
1606 sprintf(buf, "Mean: %0.1f\nStdDev: %0.1f", estimator.GetMean(), estimator.GetStandardDeviation());
1607 text += buf;
1608 }
1609 }
1610
1611 label_.SetText(text);
1581 } 1612 }
1582 1613
1583 public: 1614 public:
1584 RectangleProbeAnnotation(AnnotationsSceneLayer& that, 1615 RectangleProbeAnnotation(AnnotationsSceneLayer& that,
1585 Units units, 1616 Units units,
1592 segment2_(AddTypedPrimitive<Segment>(new Segment(*this, p2.GetX(), p1.GetY(), p2.GetX(), p2.GetY()))), 1623 segment2_(AddTypedPrimitive<Segment>(new Segment(*this, p2.GetX(), p1.GetY(), p2.GetX(), p2.GetY()))),
1593 segment3_(AddTypedPrimitive<Segment>(new Segment(*this, p2.GetX(), p2.GetY(), p1.GetX(), p2.GetY()))), 1624 segment3_(AddTypedPrimitive<Segment>(new Segment(*this, p2.GetX(), p2.GetY(), p1.GetX(), p2.GetY()))),
1594 segment4_(AddTypedPrimitive<Segment>(new Segment(*this, p1.GetX(), p2.GetY(), p1.GetX(), p1.GetY()))), 1625 segment4_(AddTypedPrimitive<Segment>(new Segment(*this, p1.GetX(), p2.GetY(), p1.GetX(), p1.GetY()))),
1595 label_(AddTypedPrimitive<Text>(new Text(that, *this))) 1626 label_(AddTypedPrimitive<Text>(new Text(that, *this)))
1596 { 1627 {
1628 TextSceneLayer content;
1629 content.SetAnchor(BitmapAnchor_CenterLeft);
1630 content.SetBorder(10);
1631 content.SetText("?");
1632
1633 label_.SetContent(content);
1597 label_.SetColor(COLOR_TEXT); 1634 label_.SetColor(COLOR_TEXT);
1598 UpdateLabel();
1599 } 1635 }
1600 1636
1601 virtual unsigned int GetHandlesCount() const ORTHANC_OVERRIDE 1637 virtual unsigned int GetHandlesCount() const ORTHANC_OVERRIDE
1602 { 1638 {
1603 return 2; 1639 return 2;
1684 else 1720 else
1685 { 1721 {
1686 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 1722 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
1687 } 1723 }
1688 1724
1689 UpdateLabel(); 1725 TagProbeAsChanged();
1690 }
1691
1692 virtual void UpdateProbe(const Scene2D& scene) ORTHANC_OVERRIDE
1693 {
1694 } 1726 }
1695 1727
1696 virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE 1728 virtual void Serialize(Json::Value& target) ORTHANC_OVERRIDE
1697 { 1729 {
1698 target = Json::objectValue; 1730 target = Json::objectValue;