1 /***********************************************************************
2 ContourLineExtractor - Class to identify contour lines from a depth image.
3 Copyright (c) 2015-2016 Oliver Kreylos
4 Copyright (c) 2020 Scottsdale Community College
6 This file is part of the Augmented Reality Sandbox (SARndbox).
8 The Augmented Reality Sandbox is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
13 The Augmented Reality Sandbox is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with the Augmented Reality Sandbox; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 ***********************************************************************/
23 #include "ContourLineExtractor.h"
25 #include <Misc/Utility.h>
26 #include <Misc/FunctionCalls.h>
27 #include <Math/Math.h>
32 /*********************************************
33 Static elements of class ContourLineExtractor:
34 *********************************************/
36 const unsigned short ContourLineExtractor::invalidLineId
= 0xffffU
;
37 const int ContourLineExtractor::walkDx
[8] = { 1, 1, 0, -1, -1, -1, 0, 1};
38 const int ContourLineExtractor::walkDy
[8] = { 0, 1, 1, 1, 0, -1, -1, -1};
42 /*************************************
43 Methods of class ContourLineExtractor:
44 *************************************/
46 void* ContourLineExtractor::extractorThreadMethod(void) {
47 unsigned int lastInputFrameVersion
= 0;
50 Kinect::FrameBuffer frame
;
52 Threads::MutexCond::Lock
inputLock(inputCond
);
54 /* Wait until a new frame arrives or the program shuts down: */
55 while(runExtractorThread
&& lastInputFrameVersion
== inputFrameVersion
)
56 inputCond
.wait(inputLock
);
58 /* Bail out if the program is shutting down: */
59 if(!runExtractorThread
)
62 /* Work on the new frame: */
64 lastInputFrameVersion
= inputFrameVersion
;
67 /* Prepare a new output contour line list: */
68 ContourLineList
& newContourLineList
= extractedContourLines
.startNewValue();
70 /* Extract contour lines from the new input frame: */
71 extractContourLines(frame
.getData
<DepthPixel
>(), newContourLineList
);
73 /* Finalize the new extracted contour lines list in the output buffer: */
74 extractedContourLines
.postNewValue();
76 /* Pass the new output frame to the registered receiver: */
77 if(contourLinesExtractedFunction
!= 0)
78 (*contourLinesExtractedFunction
)(newContourLineList
);
84 ContourLineExtractor::ContourLineExtractor(const unsigned int sDepthFrameSize
[2],
85 const ContourLineExtractor::PixelDepthCorrection
* sPixelDepthCorrection
,
86 const PTransform
& sDepthProjection
)
87 : pixelDepthCorrection(sPixelDepthCorrection
), depthProjection(sDepthProjection
),
88 inputFrameVersion(0), runExtractorThread(false),
89 maxFgDepth(0x07ffU
- 1U),
90 contourLinesExtractedFunction(0) {
92 /* Copy the depth frame size: */
93 for(int i
= 0; i
< 2; ++i
)
94 depthFrameSize
[i
] = sDepthFrameSize
[i
];
96 /* Start the hand extraction thread: */
97 runExtractorThread
= true;
98 extractorThread
.start(this, &ContourLineExtractor::extractorThreadMethod
);
101 ContourLineExtractor::~ContourLineExtractor(void) {
102 /* Shut down the extraction thread: */
104 Threads::MutexCond::Lock
inputLock(inputCond
);
105 runExtractorThread
= false;
108 extractorThread
.join();
111 void ContourLineExtractor::setMaxFgDepth(DepthPixel newMaxFgDepth
) {
112 maxFgDepth
= newMaxFgDepth
;
115 void ContourLineExtractor::extractContourLines(const ContourLineExtractor::DepthPixel
* depthFrame
,
116 ContourLineExtractor::ContourLineList
& lines
) {
118 // std::cerr << "scanning depth frame for contour lines." << std::endl;
120 /* Scan the depth image, setting all non-contour interval elevations to zero: */
121 std::vector
<unsigned int> correctedDepths
;
122 const DepthPixel
* dfPtr
= depthFrame
;
125 if (once
> 90 && once
< 92) {
126 std::cout
<< std::endl
;
127 std::cout
<< "basePlane: (" << basePlane
.getNormal()[0] << ", " << basePlane
.getNormal()[1] << ", " << basePlane
.getNormal()[2] << ") = " << basePlane
.getOffset() << std::endl
;
128 std::cout
<< "basePlaneDicEq: (" << basePlaneDicEq
[0] << ", " << basePlaneDicEq
[1] << ", " << basePlaneDicEq
[2] << ") = " << basePlaneDicEq
[3] << std::endl
;
129 const int x
= depthFrameSize
[0];
130 const int y
= depthFrameSize
[1];
132 unsigned int sealevel
= floor(0x03ffU
* basePlaneDicEq
[3]);
133 std::cout
<< "sealevel: " << sealevel
<< std::endl
;
135 // for (unsigned int i = 0; i < x * y; ++i, ++dfPtr) {
136 // if (*dfPtr > maxDepth)
139 // if (*dfPtr > sealevel && *dfPtr < sealevel + 500) {
140 // std::cout << i << ", " << float(depthFrame[i]) << ", " << depth << std::endl;
144 // depth = float(0x03ffU - *dfPtr) * basePlaneDicEq[3];
146 // depth = pixelDepthCorrection[i].correct(float(depthFrame[i])) * basePlaneDicEq[3] - sealevel;
147 // depth = basePlane.getOffset() * (pixelDepthCorrection[i].correct(float(depthFrame[i])) / 2047.0) - basePlane.getOffset();
149 // std::cout << depth;
151 // std::cout << std::endl;
153 // std::cout << ", ";
155 // if (*dfPtr < -10) {
156 // correctedDepths.push_back(0);
158 // correctedDepths.push_back(*dfPtr);
165 // for(unsigned int y = 0; y < depthFrameSize[1]; ++y, dfRowPtr += depthFrameSize[0]) {
166 // const DepthPixel* dfPtr = dfRowPtr;
167 // unsigned int x = 0;
170 // DepthPixel lastDepth = *dfPtr;
173 // for(; x < depthFrameSize[0] && *dfPtr <= maxFgDepth; ++x, ++dfPtr)
174 // lastDepth = *dfPtr;
179 /* Initialize the result list: */
182 /* Trace contiguous, non-zero values to form lines: */
186 // // std::cout<<"Hand in depth space: "<<center[0]<<", "<<center[1]<<", "<<depth<<", "<<radius<<std::endl;
188 // /* Store the hand in camera space: */
189 // ContourLine newLine;
191 // newLine.origin = depthProjection.transform(Point(center[0], center[1], center[2]));
192 // newLine.points = Geometry::dist(newHand.center,
193 // depthProjection.transform(Point(center[0], center[1], center[2])));
195 // lines.push_back(newLine);
198 // // std::cout<<"Hand in camera space: "<<newHand.center[0]<<", "<<newHand.center[1]<<", "<<newHand.center[2]<<", "<<newHand.radius<<", "<<newHand.direction<<std::endl;
202 void ContourLineExtractor::setBasePlane(const Plane
& newBasePlane
) {
203 /* Set the base plane: */
204 basePlane
= newBasePlane
;
206 /* Transform the base plane to depth image space and into a GLSL-compatible format: */
207 const PTransform::Matrix
& dpm
= depthProjection
.getMatrix();
208 const Plane::Vector
& bpn
= basePlane
.getNormal();
209 Scalar bpo
= basePlane
.getOffset();
210 for(int i
= 0; i
< 4; ++i
)
211 basePlaneDicEq
[i
] = GLfloat(dpm(0, i
) * bpn
[0] + dpm(1, i
) * bpn
[1] + dpm(2, i
) * bpn
[2] - dpm(3, i
) * bpo
);
214 void ContourLineExtractor::setContourLinesExtractedFunction(ContourLineExtractor::ContourLinesExtractedFunction
* newContourLinesExtractedFunction
) {
215 delete contourLinesExtractedFunction
;
216 contourLinesExtractedFunction
= newContourLinesExtractedFunction
;
219 void ContourLineExtractor::receiveRawFrame(const Kinect::FrameBuffer
& newFrame
) {
220 Threads::MutexCond::Lock
inputLock(inputCond
);
222 /* Store the new buffer in the input buffer: */
223 inputFrame
= newFrame
;
226 /* Signal the background thread: */