001/* 002 * Copyright (C) Photon Vision. 003 * 004 * This program is free software: you can redistribute it and/or modify 005 * it under the terms of the GNU General Public License as published by 006 * the Free Software Foundation, either version 3 of the License, or 007 * (at your option) any later version. 008 * 009 * This program is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU General Public License for more details. 013 * 014 * You should have received a copy of the GNU General Public License 015 * along with this program. If not, see <https://www.gnu.org/licenses/>. 016 */ 017 018package org.photonvision.vision.pipeline; 019 020import org.photonvision.vision.camera.QuirkyCamera; 021import org.photonvision.vision.frame.Frame; 022import org.photonvision.vision.frame.FrameStaticProperties; 023import org.photonvision.vision.frame.FrameThresholdType; 024import org.photonvision.vision.opencv.Releasable; 025import org.photonvision.vision.pipeline.result.CVPipelineResult; 026 027public abstract class CVPipeline<R extends CVPipelineResult, S extends CVPipelineSettings> 028 implements Releasable { 029 static final int MAX_MULTI_TARGET_RESULTS = 10; 030 031 protected S settings; 032 protected FrameStaticProperties frameStaticProperties; 033 protected QuirkyCamera cameraQuirks; 034 035 private final FrameThresholdType thresholdType; 036 037 // So releaseable doesn't keep track of if we double-free something. so (ew) remember that here 038 protected volatile boolean released = false; 039 040 public CVPipeline(FrameThresholdType thresholdType) { 041 this.thresholdType = thresholdType; 042 } 043 044 public FrameThresholdType getThresholdType() { 045 return thresholdType; 046 } 047 048 protected void setPipeParams( 049 FrameStaticProperties frameStaticProperties, S settings, QuirkyCamera cameraQuirks) { 050 this.settings = settings; 051 this.frameStaticProperties = frameStaticProperties; 052 this.cameraQuirks = cameraQuirks; 053 054 setPipeParamsImpl(); 055 } 056 057 protected abstract void setPipeParamsImpl(); 058 059 protected abstract R process(Frame frame, S settings); 060 061 public S getSettings() { 062 return settings; 063 } 064 065 public void setSettings(S s) { 066 this.settings = s; 067 } 068 069 public R run(Frame frame, QuirkyCamera cameraQuirks) { 070 if (released) { 071 throw new RuntimeException("Pipeline use-after-free!"); 072 } 073 if (settings == null) { 074 throw new RuntimeException("No settings provided for pipeline!"); 075 } 076 setPipeParams(frame.frameStaticProperties, settings, cameraQuirks); 077 078 // if (frame.image.getMat().empty()) { 079 // //noinspection unchecked 080 // return (R) new CVPipelineResult(0, 0, List.of(), frame); 081 // } 082 R result = process(frame, settings); 083 084 result.setImageCaptureTimestampNanos(frame.timestampNanos); 085 086 return result; 087 } 088 089 /** 090 * Release any native memory associated with this pipeline. Called by pipelinemanager at pipeline 091 * switch. Stubbed out, but override if needed. 092 */ 093 @Override 094 public void release() { 095 released = true; 096 } 097}