detection.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. from datetime import datetime
  2. from zoneinfo import ZoneInfo
  3. from app.constants import DiseaseGrade, TaskStatus
  4. from app.models import db
  5. class Detection(db.Model):
  6. """
  7. 检测分割记录类,表示数据库中的 'detection' 表。
  8. 每一条记录对应一次检测任务,包含检测分割结果图像,
  9. 以及与检测分割任务相关的各类统计信息(如病害数量、面积、形状复杂度等)及评估描述。
  10. Attributes:
  11. detection_id (int): 检测记录的唯一标识符(主键)。
  12. result_path (str): 检测和分割的结果存储路径。
  13. disease_count (int): 病害的数量。
  14. disease_perimeter (float): 病害的周长。
  15. disease_area (float): 病害的面积。
  16. shape_complexity (float): 病害形状的复杂度。
  17. texture_roughness (float): 病害的纹理粗糙度。
  18. crack_width (float): 裂缝的宽度(适用于裂缝病害)。
  19. avg_hue (float): 病害的平均色调(适用于锈蚀等病害)。
  20. disease_severity_score (float): 病害严重性得分。
  21. disease_grade (str): 病害的评估等级,使用枚举类型('mild', 'moderate', 'severe', 'critical')。
  22. disease_description (str): 病害评估的描述信息。
  23. detection_duration (float): 检测分割耗时(ms)。
  24. avg_frame_detection_duration (float): 帧平均检测分割耗时(ms)。
  25. status (str): 任务状态,使用枚举类型('pending', 'in_progress', 'completed', 'failed')。
  26. detection_at (datetime): 检测任务执行的时间,自动生成。
  27. updated_at (datetime): 记录最后更新时间,自动更新。
  28. owner_id (int): 执行该检测任务的用户 ID(外键)。
  29. model_id (int): 使用的模型 ID(外键)。
  30. media_id (int): 使用的媒体文件 ID(外键)。
  31. Relationships:
  32. owner (User): 每条检测记录关联一个用户,表示该任务由哪个用户执行。
  33. model (Model): 每条记录关联一个模型,表示该任务使用的模型。
  34. media (Media): 每条记录关联一个媒体文件,表示该任务使用的媒体文件。
  35. """
  36. __tablename__ = 'detection'
  37. detection_id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 检测分割记录 ID
  38. result_path = db.Column(db.String(255)) # 检测分割结果路径
  39. disease_count = db.Column(db.Integer, default=0) # 病害数量
  40. disease_perimeter = db.Column(db.Float, default=0.0) # 病害周长
  41. disease_area = db.Column(db.Float, default=0.0) # 病害面积
  42. shape_complexity = db.Column(db.Float, default=0.0) # 形状复杂度
  43. texture_roughness = db.Column(db.Float, default=0.0) # 纹理粗糙度
  44. crack_width = db.Column(db.Float, default=0.0) # 裂缝宽度(适用裂缝等)
  45. avg_hue = db.Column(db.Float, default=0.0) # 平均色调(适用锈蚀等)
  46. disease_severity_score = db.Column(db.Float, default=0.0, nullable=False) # 病害严重性得分
  47. disease_grade = db.Column(db.Enum(DiseaseGrade), default=DiseaseGrade.MILD, nullable=False) # 病害评估等级
  48. disease_description = db.Column(db.Text, default='暂无描述') # 病害评估描述
  49. detection_duration = db.Column(db.Float, default=0.0) # 检测分割耗时(ms)
  50. avg_frame_detection_duration = db.Column(db.Float, default=0.0) # 帧平均检测分割耗时(ms)
  51. status = db.Column(db.Enum(TaskStatus), default=TaskStatus.PENDING, nullable=False) # 任务状态
  52. detection_at = db.Column(db.DateTime, default=lambda: datetime.now(ZoneInfo("Asia/Shanghai"))) # 检测时间
  53. updated_at = db.Column(db.DateTime, default=lambda: datetime.now(ZoneInfo("Asia/Shanghai")),
  54. onupdate=lambda: datetime.now(ZoneInfo("Asia/Shanghai"))) # 最后更新时间
  55. owner_id = db.Column(db.Integer, db.ForeignKey('user.user_id'), nullable=False) # 所属用户 ID(外键)
  56. model_id = db.Column(db.Integer, db.ForeignKey('model.model_id'), nullable=False) # 使用模型 ID(外键)
  57. media_id = db.Column(db.Integer, db.ForeignKey('media.media_id'), nullable=False) # 使用媒体 ID(外键)
  58. # 设置与 User 表的关系:一次检测分割只属于一个用户
  59. owner = db.relationship('User', backref=db.backref('detections', lazy=True))
  60. # 设置与 Model 表的关系:一次检测分割只使用一个模型
  61. model = db.relationship('Model', backref=db.backref('detections', lazy=True))
  62. # 设置与 Media 表的关系:一次检测分割只使用一份媒体文件
  63. media = db.relationship('Media', backref=db.backref('detections', lazy=True))
  64. def __repr__(self):
  65. return (f"Detection(detection_id={self.detection_id}, "
  66. f"result_path={self.result_path}, "
  67. f"disease_count={self.disease_count}, "
  68. f"disease_perimeter={self.disease_perimeter}, "
  69. f"disease_area={self.disease_area}, "
  70. f"shape_complexity={self.shape_complexity}, "
  71. f"texture_roughness={self.texture_roughness}, "
  72. f"crack_width={self.crack_width}, "
  73. f"avg_hue={self.avg_hue}, "
  74. f"disease_severity_score={self.disease_severity_score}, "
  75. f"disease_grade={self.disease_grade.name}, "
  76. f"disease_description={self.disease_description}, "
  77. f"detection_duration={self.detection_duration}, "
  78. f"avg_frame_detection_duration={self.avg_frame_detection_duration}, "
  79. f"status={self.status.name}, "
  80. f"detection_at={self.detection_at}, "
  81. f"updated_at={self.updated_at}, "
  82. f"owner_id={self.owner_id}, "
  83. f"model_id={self.model_id}, "
  84. f"media_id={self.media_id})")
  85. def to_dict(self):
  86. """
  87. 将 Detection 实例转化为字典。
  88. """
  89. return {
  90. 'detection_id': self.detection_id,
  91. 'result_path': self.result_path,
  92. 'disease_count': self.disease_count,
  93. 'disease_perimeter': self.disease_perimeter,
  94. 'disease_area': self.disease_area,
  95. 'shape_complexity': self.shape_complexity,
  96. 'texture_roughness': self.texture_roughness,
  97. 'crack_width': self.crack_width,
  98. 'avg_hue': self.avg_hue,
  99. 'disease_severity_score': self.disease_severity_score,
  100. 'disease_grade': self.disease_grade.name,
  101. 'disease_description': self.disease_description,
  102. 'detection_duration': self.detection_duration,
  103. 'avg_frame_detection_duration': self.avg_frame_detection_duration,
  104. 'status': self.status.name,
  105. 'detection_at': self.detection_at,
  106. 'updated_at': self.updated_at,
  107. 'owner_id': self.owner_id,
  108. 'model_id': self.model_id,
  109. 'media_id': self.media_id
  110. }