Commit 909ad7a031135ca8ae05bfc1c94d46486f33fec5

Authored by caotto
2 parents fabf7784 96384bbc

Merge pull request #294 from biometrics/stream_galleries

Refactor video handling in stream
openbr/core/qtutils.cpp
... ... @@ -484,5 +484,22 @@ float overlap(const QRectF &r, const QRectF &s) {
484 484 return (intersection.width()*intersection.height())/(r.width()*r.height());
485 485 }
486 486  
  487 +
  488 +QString getAbsolutePath(const QString &filename)
  489 +{
  490 + // Try adding the global path, if present
  491 + QString withPath = (Globals->path.isEmpty() ? "" : Globals->path + "/") + filename;
  492 +
  493 + // we weren't necessarily using it to begin with, so see if that file
  494 + // exists
  495 + QFileInfo wpInfo(withPath);
  496 + if (wpInfo.exists() )
  497 + return wpInfo.absoluteFilePath();
  498 +
  499 + // If no, just use the nominal filename
  500 + return QFileInfo(filename).absoluteFilePath();
  501 +}
  502 +
  503 +
487 504 } // namespace QtUtils
488 505  
... ...
openbr/core/qtutils.h
... ... @@ -50,6 +50,7 @@ namespace QtUtils
50 50 void emptyDir(QDir &dir);
51 51 void deleteDir(QDir &dir);
52 52 QString find(const QString &file, const QString &alt);
  53 + QString getAbsolutePath(const QString &filename);
53 54  
54 55 /**** String Utilities ****/
55 56 bool toBool(const QString &string);
... ...
openbr/plugins/algorithms.cpp
... ... @@ -48,12 +48,12 @@ class AlgorithmsInitializer : public Initializer
48 48 Globals->abbreviations.insert("4SF", "Open+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+Affine(128,128,0.33,0.45)+(Grid(10,10)+SIFTDescriptor(12)+ByRow)/(Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2)+RectRegions(8,8,6,6)+Hist(59))+PCA(0.95)+Cat+Normalize(L2)+Dup(12)+RndSubspace(0.05,1)+LDA(0.98)+Cat+PCA(0.95)+Normalize(L1)+Quantize:NegativeLogPlusOne(ByteL1)");
49 49  
50 50 // Video
51   - Globals->abbreviations.insert("DisplayVideo", "Stream(FPSLimit(30)+Show(false,[FrameNumber])+Discard)");
52   - Globals->abbreviations.insert("PerFrameDetection", "Stream(SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+RestoreMat(original)+Draw(inPlace=true)+Show(false,[FrameNumber])+Discard)");
53   - Globals->abbreviations.insert("AgeGenderDemo", "Stream(SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+Expand+<FaceClassificationRegistration>+<FaceClassificationExtraction>+<AgeRegressor>/<GenderClassifier>+Discard+RestoreMat(original)+Draw(inPlace=true)+DrawPropertiesPoint([Age,Gender],Affine_0,inPlace=true)+SaveMat(original)+Discard+Contract+RestoreMat(original)+FPSCalc+Show(false,[AvgFPS,Age,Gender])+Discard)");
54   - Globals->abbreviations.insert("ShowOpticalFlowField", "Stream(SaveMat(original)+AggregateFrames(2)+OpticalFlow(useMagnitude=false)+Grid(100,100)+DrawOpticalFlow+FPSLimit(30)+Show(false)+Discard)");
55   - Globals->abbreviations.insert("ShowOpticalFlowMagnitude", "Stream(AggregateFrames(2)+OpticalFlow+Normalize(Range,false,0,255)+Cvt(Color)+Draw+FPSLimit(30)+Show(false)+Discard)");
56   - Globals->abbreviations.insert("ShowMotionSegmentation", "Stream(DropFrames(5)+AggregateFrames(2)+OpticalFlow+CvtUChar+WatershedSegmentation+DrawSegmentation+Draw+FPSLimit(30)+Show(false)+Discard)");
  51 + Globals->abbreviations.insert("DisplayVideo", "FPSLimit(30)+Show(false,[FrameNumber])+Discard");
  52 + Globals->abbreviations.insert("PerFrameDetection", "SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+RestoreMat(original)+Draw(inPlace=true)+Show(false,[FrameNumber])+Discard");
  53 + Globals->abbreviations.insert("AgeGenderDemo", "SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+Expand+<FaceClassificationRegistration>+<FaceClassificationExtraction>+<AgeRegressor>/<GenderClassifier>+Discard+RestoreMat(original)+Draw(inPlace=true)+DrawPropertiesPoint([Age,Gender],Affine_0,inPlace=true)+SaveMat(original)+Discard+Contract+RestoreMat(original)+FPSCalc+Show(false,[AvgFPS,Age,Gender])+Discard");
  54 + Globals->abbreviations.insert("ShowOpticalFlowField", "SaveMat(original)+AggregateFrames(2)+OpticalFlow(useMagnitude=false)+Grid(100,100)+DrawOpticalFlow+FPSLimit(30)+Show(false)+Discard");
  55 + Globals->abbreviations.insert("ShowOpticalFlowMagnitude", "AggregateFrames(2)+OpticalFlow+Normalize(Range,false,0,255)+Cvt(Color)+Draw+FPSLimit(30)+Show(false)+Discard");
  56 + Globals->abbreviations.insert("ShowMotionSegmentation", "DropFrames(5)+AggregateFrames(2)+OpticalFlow+CvtUChar+WatershedSegmentation+DrawSegmentation+Draw+FPSLimit(30)+Show(false)+Discard");
57 57  
58 58 Globals->abbreviations.insert("HOGVideo", "Stream(DropFrames(5)+Cvt(Gray)+Grid(5,5)+ROIFromPts(32,24)+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat)+Contract+CatRows+KMeans(500)+Hist(500)+SVM");
59 59 Globals->abbreviations.insert("HOFVideo", "Stream(DropFrames(5)+Grid(5,5)+AggregateFrames(2)+OpticalFlow+ROIFromPts(32,24)+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat)+Contract+CatRows+KMeans(500)+Hist(500)");
... ...
openbr/plugins/gallery.cpp
... ... @@ -34,6 +34,8 @@
34 34 #include "openbr/core/opencvutils.h"
35 35 #include "openbr/core/qtutils.h"
36 36  
  37 +#include <fstream>
  38 +
37 39 #ifdef CVMATIO
38 40 #include "MatlabIO.hpp"
39 41 #include "MatlabIOContainer.hpp"
... ... @@ -1743,6 +1745,330 @@ BR_REGISTER(Gallery, vbbGallery)
1743 1745  
1744 1746 #endif
1745 1747  
  1748 +
  1749 +// Read a video frame by frame using cv::VideoCapture
  1750 +class videoGallery : public Gallery
  1751 +{
  1752 + Q_OBJECT
  1753 +public:
  1754 + qint64 idx;
  1755 + ~videoGallery()
  1756 + {
  1757 + video.release();
  1758 + }
  1759 +
  1760 + static QMutex openLock;
  1761 +
  1762 + virtual void deferredInit()
  1763 + {
  1764 + bool status = video.open(QtUtils::getAbsolutePath(file.name).toStdString());
  1765 +
  1766 + if (!status)
  1767 + qFatal("Failed to open file %s with path %s", qPrintable(file.name), qPrintable(QtUtils::getAbsolutePath(file.name)));
  1768 + }
  1769 +
  1770 + TemplateList readBlock(bool *done)
  1771 + {
  1772 + if (!video.isOpened()) {
  1773 + // opening videos appears to not be thread safe on windows
  1774 + QMutexLocker lock(&openLock);
  1775 +
  1776 + deferredInit();
  1777 + idx = 0;
  1778 + }
  1779 +
  1780 + Template output;
  1781 + output.file = file;
  1782 + output.m() = cv::Mat();
  1783 +
  1784 + cv::Mat temp;
  1785 + bool res = video.read(temp);
  1786 +
  1787 + if (!res) {
  1788 + // The video capture broke, return an empty list.
  1789 + output.m() = cv::Mat();
  1790 + video.release();
  1791 + *done = true;
  1792 + return TemplateList();
  1793 + }
  1794 +
  1795 + // This clone is critical, if we don't do it then the output matrix will
  1796 + // be an alias of an internal buffer of the video source, leading to various
  1797 + // problems later.
  1798 + output.m() = temp.clone();
  1799 +
  1800 + output.file.set("progress", idx);
  1801 + idx++;
  1802 +
  1803 + TemplateList rVal;
  1804 + rVal.append(temp);
  1805 + *done = false;
  1806 + return rVal;
  1807 + }
  1808 +
  1809 + void write(const Template &t)
  1810 + {
  1811 + (void)t; qFatal("Not implemented");
  1812 + }
  1813 +
  1814 +protected:
  1815 + cv::VideoCapture video;
  1816 +};
  1817 +BR_REGISTER(Gallery,videoGallery)
  1818 +
  1819 +QMutex videoGallery::openLock;
  1820 +
  1821 +class aviGallery : public videoGallery
  1822 +{
  1823 + Q_OBJECT
  1824 +};
  1825 +BR_REGISTER(Gallery, aviGallery)
  1826 +
  1827 +class wmvGallery : public videoGallery
  1828 +{
  1829 + Q_OBJECT
  1830 +};
  1831 +BR_REGISTER(Gallery, wmvGallery)
  1832 +
  1833 +// Mostly the same as videoGallery, but we open the VideoCapture with an integer index
  1834 +// rather than file name/web address
  1835 +class webcamGallery : public videoGallery
  1836 +{
  1837 +public:
  1838 + Q_OBJECT
  1839 +
  1840 + void deferredInit()
  1841 + {
  1842 + bool intOK = false;
  1843 + int anInt = file.baseName().toInt(&intOK);
  1844 +
  1845 + if (!intOK)
  1846 + qFatal("Expected integer basename, got %s", qPrintable(file.baseName()));
  1847 +
  1848 + bool rc = video.open(anInt);
  1849 +
  1850 + if (!rc)
  1851 + qFatal("Failed to open webcam with index: %s", qPrintable(file.baseName()));
  1852 + }
  1853 +
  1854 +};
  1855 +BR_REGISTER(Gallery,webcamGallery)
  1856 +
  1857 +class seqGallery : public Gallery
  1858 +{
  1859 +public:
  1860 + Q_OBJECT
  1861 +
  1862 + bool open()
  1863 + {
  1864 + seqFile.open(QtUtils::getAbsolutePath(file.name).toStdString().c_str(), std::ios::in | std::ios::binary | std::ios::ate);
  1865 + if (!isOpen()) {
  1866 + qDebug("Failed to open file %s for reading", qPrintable(file.name));
  1867 + return false;
  1868 + }
  1869 +
  1870 + int headSize = 1024;
  1871 + // start at end of file to get full size
  1872 + int fileSize = seqFile.tellg();
  1873 + if (fileSize < headSize) {
  1874 + qDebug("No header in seq file");
  1875 + return false;
  1876 + }
  1877 +
  1878 + // first 4 bytes store 0xEDFE, next 24 store 'Norpix seq '
  1879 + char firstFour[4];
  1880 + seqFile.seekg(0, std::ios::beg);
  1881 + seqFile.read(firstFour, 4);
  1882 + char nextTwentyFour[24];
  1883 + readText(24, nextTwentyFour);
  1884 + if (firstFour[0] != (char)0xED || firstFour[1] != (char)0xFE || strncmp(nextTwentyFour, "Norpix seq", 10) != 0) {
  1885 + qDebug("Invalid header in seq file");
  1886 + return false;
  1887 + }
  1888 +
  1889 + // next 8 bytes for version (skipped below) and header size (1024), then 512 for descr
  1890 + seqFile.seekg(4, std::ios::cur);
  1891 + int hSize = readInt();
  1892 + if (hSize != headSize) {
  1893 + qDebug("Invalid header size");
  1894 + return false;
  1895 + }
  1896 + char desc[512];
  1897 + readText(512, desc);
  1898 + file.set("Description", QString(desc));
  1899 +
  1900 + width = readInt();
  1901 + height = readInt();
  1902 + // get # channels from bit depth
  1903 + numChan = readInt()/8;
  1904 + int imageBitDepthReal = readInt();
  1905 + if (imageBitDepthReal != 8) {
  1906 + qDebug("Invalid bit depth");
  1907 + return false;
  1908 + }
  1909 + // the size of just the image part of a raw img
  1910 + imgSizeBytes = readInt();
  1911 +
  1912 + int imgFormatInt = readInt();
  1913 + if (imgFormatInt == 100 || imgFormatInt == 200 || imgFormatInt == 101) {
  1914 + imgFormat = "raw";
  1915 + } else if (imgFormatInt == 102 || imgFormatInt == 201 || imgFormatInt == 103 ||
  1916 + imgFormatInt == 1 || imgFormatInt == 2) {
  1917 + imgFormat = "compressed";
  1918 + } else {
  1919 + qFatal("unsupported image format");
  1920 + }
  1921 +
  1922 + numFrames = readInt();
  1923 + // skip empty int
  1924 + seqFile.seekg(4, std::ios::cur);
  1925 + // the size of a full raw file, with extra crap after img data
  1926 + trueImgSizeBytes = readInt();
  1927 +
  1928 + // gather all the frame positions in an array
  1929 + seekPos.reserve(numFrames);
  1930 + // start at end of header
  1931 + seekPos.append(headSize);
  1932 + // extra 8 bytes at end of img
  1933 + int extra = 8;
  1934 + for (int i=1; i<numFrames; i++) {
  1935 + int s;
  1936 + // compressed images have different sizes
  1937 + // the first byte at the beginning of the file
  1938 + // says how big the current img is
  1939 + if (imgFormat == "compressed") {
  1940 + int lastPos = seekPos[i-1];
  1941 + seqFile.seekg(lastPos, std::ios::beg);
  1942 + int currSize = readInt();
  1943 + s = lastPos + currSize + extra;
  1944 +
  1945 + // but there might be 16 extra bytes instead of 8...
  1946 + if (i == 1) {
  1947 + seqFile.seekg(s, std::ios::beg);
  1948 + char zero;
  1949 + seqFile.read(&zero, 1);
  1950 + if (zero == 0) {
  1951 + s += 8;
  1952 + extra += 8;
  1953 + }
  1954 + }
  1955 + }
  1956 + // raw images are all the same size
  1957 + else {
  1958 + s = headSize + (i*trueImgSizeBytes);
  1959 + }
  1960 +
  1961 + seekPos.enqueue(s);
  1962 + }
  1963 +
  1964 +#ifdef CVMATIO
  1965 + if (basis.file.contains("vbb")) {
  1966 + QString vbb = basis.file.get<QString>("vbb");
  1967 + annotations = TemplateList::fromGallery(File(vbb));
  1968 + }
  1969 +#else
  1970 + qWarning("cvmatio not installed, bounding boxes will not be available. Add -DBR_WITH_CVMATIO cmake flag to install.");
  1971 +#endif
  1972 +
  1973 + return true;
  1974 + }
  1975 +
  1976 + bool isOpen()
  1977 + {
  1978 + return seqFile.is_open();
  1979 + }
  1980 +
  1981 + void close()
  1982 + {
  1983 + seqFile.close();
  1984 + }
  1985 +
  1986 + TemplateList readBlock(bool *done)
  1987 + {
  1988 + if (!isOpen()) {
  1989 + if (!open())
  1990 + qFatal("Failed to open file %s for reading", qPrintable(file.name));
  1991 + else
  1992 + idx = 0;
  1993 + }
  1994 +
  1995 + // if we've reached the last frame, we're done
  1996 + if (seekPos.size() == 0) {
  1997 + *done = true;
  1998 + return TemplateList();
  1999 + }
  2000 +
  2001 + seqFile.seekg(seekPos.dequeue(), std::ios::beg);
  2002 +
  2003 + cv::Mat temp;
  2004 + // let imdecode do all the work to decode the compressed img
  2005 + if (imgFormat == "compressed") {
  2006 + int imgSize = readInt() - 4;
  2007 + std::vector<char> imgBuf(imgSize);
  2008 + seqFile.read(&imgBuf[0], imgSize);
  2009 + // flags < 0 means load image as-is (keep color info if available)
  2010 + cv::imdecode(imgBuf, -1, &temp);
  2011 + }
  2012 + // raw images can be loaded straight into a Mat
  2013 + else {
  2014 + char *imgBuf = new char[imgSizeBytes];
  2015 + seqFile.read(imgBuf, imgSizeBytes);
  2016 + int type = (numChan == 1 ? CV_8UC1 : CV_8UC3);
  2017 + temp = cv::Mat(height, width, type, imgBuf);
  2018 + }
  2019 + Template output;
  2020 + output.file = file;
  2021 + if (!annotations.empty()) {
  2022 + output.file.setRects(annotations.first().file.rects());
  2023 + annotations.removeFirst();
  2024 + }
  2025 + output.m() = temp;
  2026 + output.file.set("position",idx);
  2027 + idx++;
  2028 +
  2029 + *done = false;
  2030 + TemplateList rVal;
  2031 + rVal.append(output);
  2032 +
  2033 + return rVal;
  2034 + }
  2035 +
  2036 + void write(const Template &t)
  2037 + {
  2038 + (void) t;
  2039 + qFatal("Not implemented.");
  2040 + }
  2041 +
  2042 +private:
  2043 + qint64 idx;
  2044 + int readInt()
  2045 + {
  2046 + int num;
  2047 + seqFile.read((char*)&num, 4);
  2048 + return num;
  2049 + }
  2050 +
  2051 + // apparently the text in seq files is 16 bit characters (UTF-16?)
  2052 + // since we don't really need the last byte, snad since it gets interpreted as
  2053 + // a terminating char, let's just grab the first byte for storage
  2054 + void readText(int bytes, char *buffer)
  2055 + {
  2056 + seqFile.read(buffer, bytes);
  2057 + for (int i=0; i<bytes; i+=2) {
  2058 + buffer[i/2] = buffer[i];
  2059 + }
  2060 + buffer[bytes/2] = '\0';
  2061 + }
  2062 +
  2063 +protected:
  2064 + std::ifstream seqFile;
  2065 + QQueue<int> seekPos;
  2066 + int width, height, numChan, imgSizeBytes, trueImgSizeBytes, numFrames;
  2067 + QString imgFormat;
  2068 + TemplateList annotations;
  2069 +};
  2070 +BR_REGISTER(Gallery, seqGallery)
  2071 +
1746 2072 void FileGallery::init()
1747 2073 {
1748 2074 f.setFileName(file);
... ...
openbr/plugins/stream.cpp
... ... @@ -23,10 +23,9 @@ class Idiocy : public QObject
23 23 {
24 24 Q_OBJECT
25 25 public:
26   - enum StreamModes { StreamVideo,
27   - DistributeFrames,
28   - StreamGallery,
29   - Auto};
  26 + enum StreamModes { DistributeFrames,
  27 + StreamGallery
  28 + };
30 29  
31 30 Q_ENUMS(StreamModes)
32 31 };
... ... @@ -207,88 +206,8 @@ public:
207 206 virtual bool getNextTemplate(Template &output)=0;
208 207 protected:
209 208 Template basis;
210   - string getAbsolutePath(QString filename)
211   - {
212   - // Yes, we should specify absolute path:
213   - // http://stackoverflow.com/questions/9396459/loading-a-video-in-opencv-in-python
214   - QString fileName = (Globals->path.isEmpty() ? "" : Globals->path + "/") + filename;
215   - return QFileInfo(fileName).absoluteFilePath().toStdString();
216   - }
217 209 };
218 210  
219   -static QMutex openLock;
220   -
221   -// Read a video frame by frame using cv::VideoCapture
222   -class VideoReader : public TemplateProcessor
223   -{
224   -public:
225   - VideoReader() {}
226   -
227   - bool open(Template &input)
228   - {
229   - basis = input;
230   -
231   - // We can open either files (well actually this includes addresses of ip cameras
232   - // through ffmpeg), or webcams. Webcam VideoCaptures are created through a separate
233   - // overload of open that takes an integer, not a string.
234   - // So, does this look like an integer?
235   - bool is_int = false;
236   - int anInt = input.file.name.toInt(&is_int);
237   - if (is_int)
238   - {
239   - bool rc = video.open(anInt);
240   -
241   - if (!rc)
242   - {
243   - qDebug("open failed!");
244   - }
245   - if (!video.isOpened())
246   - {
247   - qDebug("Video not open!");
248   - }
249   - } else {
250   - // On windows, this appears to not be thread-safe
251   - QMutexLocker lock(&openLock);
252   - video.open(getAbsolutePath(input.file.name));
253   - }
254   -
255   - return video.isOpened();
256   - }
257   -
258   - bool isOpen() { return video.isOpened(); }
259   -
260   - void close() { video.release(); }
261   -
262   - bool getNextTemplate(Template &output)
263   - {
264   - if (!isOpen()) {
265   - qDebug("video source is not open");
266   - return false;
267   - }
268   - output.file = basis.file;
269   - output.m() = cv::Mat();
270   -
271   - cv::Mat temp;
272   - bool res = video.read(temp);
273   -
274   - if (!res) {
275   - // The video capture broke, return false.
276   - output.m() = cv::Mat();
277   - close();
278   - return false;
279   - }
280   -
281   - // This clone is critical, if we don't do it then the matrix will
282   - // be an alias of an internal buffer of the video source, leading
283   - // to various problems later.
284   - output.m() = temp.clone();
285   - return true;
286   - }
287   -protected:
288   - cv::VideoCapture video;
289   -};
290   -
291   -
292 211 struct StreamGallery : public TemplateProcessor
293 212 {
294 213 bool open(Template &input)
... ... @@ -387,199 +306,6 @@ protected:
387 306 bool data_ok;
388 307 };
389 308  
390   -class SeqReader : public TemplateProcessor
391   -{
392   -public:
393   - SeqReader() {}
394   -
395   - bool open(Template &input)
396   - {
397   - basis = input;
398   -
399   - seqFile.open(getAbsolutePath(input.file.name).c_str(), ios::in | ios::binary | ios::ate);
400   - if (!isOpen()) return false;
401   -
402   - int headSize = 1024;
403   - // start at end of file to get full size
404   - int fileSize = seqFile.tellg();
405   - if (fileSize < headSize) {
406   - qDebug("No header in seq file");
407   - return false;
408   - }
409   -
410   - // first 4 bytes store 0xEDFE, next 24 store 'Norpix seq '
411   - char firstFour[4];
412   - seqFile.seekg(0, ios::beg);
413   - seqFile.read(firstFour, 4);
414   - char nextTwentyFour[24];
415   - readText(24, nextTwentyFour);
416   - if (firstFour[0] != (char)0xED || firstFour[1] != (char)0xFE || strncmp(nextTwentyFour, "Norpix seq", 10) != 0) {
417   - qDebug("Invalid header in seq file");
418   - return false;
419   - }
420   -
421   - // next 8 bytes for version (skipped below) and header size (1024), then 512 for descr
422   - seqFile.seekg(4, ios::cur);
423   - int hSize = readInt();
424   - if (hSize != headSize) {
425   - qDebug("Invalid header size");
426   - return false;
427   - }
428   - char desc[512];
429   - readText(512, desc);
430   - basis.file.set("Description", QString(desc));
431   -
432   - width = readInt();
433   - height = readInt();
434   - // get # channels from bit depth
435   - numChan = readInt()/8;
436   - int imageBitDepthReal = readInt();
437   - if (imageBitDepthReal != 8) {
438   - qDebug("Invalid bit depth");
439   - return false;
440   - }
441   - // the size of just the image part of a raw img
442   - imgSizeBytes = readInt();
443   -
444   - int imgFormatInt = readInt();
445   - if (imgFormatInt == 100 || imgFormatInt == 200 || imgFormatInt == 101) {
446   - imgFormat = "raw";
447   - } else if (imgFormatInt == 102 || imgFormatInt == 201 || imgFormatInt == 103 ||
448   - imgFormatInt == 1 || imgFormatInt == 2) {
449   - imgFormat = "compressed";
450   - } else {
451   - qFatal("unsupported image format");
452   - }
453   -
454   - numFrames = readInt();
455   - // skip empty int
456   - seqFile.seekg(4, ios::cur);
457   - // the size of a full raw file, with extra crap after img data
458   - trueImgSizeBytes = readInt();
459   -
460   - // gather all the frame positions in an array
461   - seekPos.reserve(numFrames);
462   - // start at end of header
463   - seekPos.append(headSize);
464   - // extra 8 bytes at end of img
465   - int extra = 8;
466   - for (int i=1; i<numFrames; i++) {
467   - int s;
468   - // compressed images have different sizes
469   - // the first byte at the beginning of the file
470   - // says how big the current img is
471   - if (imgFormat == "compressed") {
472   - int lastPos = seekPos[i-1];
473   - seqFile.seekg(lastPos, ios::beg);
474   - int currSize = readInt();
475   - s = lastPos + currSize + extra;
476   -
477   - // but there might be 16 extra bytes instead of 8...
478   - if (i == 1) {
479   - seqFile.seekg(s, ios::beg);
480   - char zero;
481   - seqFile.read(&zero, 1);
482   - if (zero == 0) {
483   - s += 8;
484   - extra += 8;
485   - }
486   - }
487   - }
488   - // raw images are all the same size
489   - else {
490   - s = headSize + (i*trueImgSizeBytes);
491   - }
492   -
493   - seekPos.enqueue(s);
494   - }
495   -
496   -#ifdef CVMATIO
497   - if (basis.file.contains("vbb")) {
498   - QString vbb = basis.file.get<QString>("vbb");
499   - annotations = TemplateList::fromGallery(File(vbb));
500   - }
501   -#else
502   - qWarning("cvmatio not installed, bounding boxes will not be available. Add -DBR_WITH_CVMATIO cmake flag to install.");
503   -#endif
504   -
505   - return true;
506   - }
507   -
508   - bool isOpen()
509   - {
510   - return seqFile.is_open();
511   - }
512   -
513   - void close()
514   - {
515   - seqFile.close();
516   - }
517   -
518   - bool getNextTemplate(Template &output)
519   - {
520   - if (!isOpen()) {
521   - qDebug("Seq not open");
522   - return false;
523   - }
524   - // if we've reached the last frame, we're done
525   - if (seekPos.size() == 0) return false;
526   -
527   - seqFile.seekg(seekPos.dequeue(), ios::beg);
528   -
529   - Mat temp;
530   - // let imdecode do all the work to decode the compressed img
531   - if (imgFormat == "compressed") {
532   - int imgSize = readInt() - 4;
533   - vector<char> imgBuf(imgSize);
534   - seqFile.read(&imgBuf[0], imgSize);
535   - // flags < 0 means load image as-is (keep color info if available)
536   - imdecode(imgBuf, -1, &temp);
537   - }
538   - // raw images can be loaded straight into a Mat
539   - else {
540   - char *imgBuf = new char[imgSizeBytes];
541   - seqFile.read(imgBuf, imgSizeBytes);
542   - int type = (numChan == 1 ? CV_8UC1 : CV_8UC3);
543   - temp = Mat(height, width, type, imgBuf);
544   - }
545   -
546   - output.file = basis.file;
547   - if (!annotations.empty()) {
548   - output.file.setRects(annotations.first().file.rects());
549   - annotations.removeFirst();
550   - }
551   - output.m() = temp;
552   -
553   - return true;
554   - }
555   -private:
556   - int readInt()
557   - {
558   - int num;
559   - seqFile.read((char*)&num, 4);
560   - return num;
561   - }
562   -
563   - // apparently the text in seq files is 16 bit characters (UTF-16?)
564   - // since we don't really need the last byte, snad since it gets interpreted as
565   - // a terminating char, let's just grab the first byte for storage
566   - void readText(int bytes, char *buffer)
567   - {
568   - seqFile.read(buffer, bytes);
569   - for (int i=0; i<bytes; i+=2) {
570   - buffer[i/2] = buffer[i];
571   - }
572   - buffer[bytes/2] = '\0';
573   - }
574   -
575   -protected:
576   - ifstream seqFile;
577   - QQueue<int> seekPos;
578   - int width, height, numChan, imgSizeBytes, trueImgSizeBytes, numFrames;
579   - QString imgFormat;
580   - TemplateList annotations;
581   -};
582   -
583 309 // Interface for sequentially getting data from some data source.
584 310 // Given a TemplateList, return single template frames sequentially by applying a TemplateProcessor
585 311 // to each individual template.
... ... @@ -650,7 +376,6 @@ public:
650 376 return true;
651 377 }
652 378  
653   -
654 379 // non-blocking version of getFrame
655 380 // Returns a NULL FrameData if too many frames are out, or the
656 381 // data source is broken. Sets last_frame to true iff the FrameData
... ... @@ -744,19 +469,7 @@ protected:
744 469 frameSource->close();
745 470  
746 471 Template curr = this->templates[current_template_idx];
747   - if (mode == br::Idiocy::Auto)
748   - {
749   - delete frameSource;
750   - if (curr.empty()) {
751   - if (curr.file.name.right(3) == "seq")
752   - frameSource = new SeqReader();
753   - else
754   - frameSource = new VideoReader();
755   - }
756   - else
757   - frameSource = new DirectReturn();
758   - }
759   - else if (mode == br::Idiocy::DistributeFrames)
  472 + if (mode == br::Idiocy::DistributeFrames)
760 473 {
761 474 if (!frameSource)
762 475 frameSource = new DirectReturn();
... ... @@ -766,15 +479,6 @@ protected:
766 479 if (!frameSource)
767 480 frameSource = new StreamGallery();
768 481 }
769   - else if (mode == br::Idiocy::StreamVideo)
770   - {
771   - if (!frameSource) {
772   - if (curr.file.name.right(3) == "seq")
773   - frameSource = new SeqReader();
774   - else
775   - frameSource = new VideoReader();
776   - }
777   - }
778 482 open_res = frameSource->open(curr);
779 483 if (!open_res)
780 484 {
... ... @@ -1271,7 +975,7 @@ public:
1271 975 Q_PROPERTY(br::Idiocy::StreamModes readMode READ get_readMode WRITE set_readMode RESET reset_readMode)
1272 976 Q_PROPERTY(br::Transform* endPoint READ get_endPoint WRITE set_endPoint RESET reset_endPoint STORED true)
1273 977 BR_PROPERTY(int, activeFrames, 100)
1274   - BR_PROPERTY(br::Idiocy::StreamModes, readMode, br::Idiocy::Auto)
  978 + BR_PROPERTY(br::Idiocy::StreamModes, readMode, br::Idiocy::StreamGallery)
1275 979 BR_PROPERTY(br::Transform*, endPoint, make("CollectOutput"))
1276 980  
1277 981 friend class StreamTransfrom;
... ... @@ -1589,7 +1293,7 @@ public:
1589 1293 Q_PROPERTY(br::Idiocy::StreamModes readMode READ get_readMode WRITE set_readMode RESET reset_readMode)
1590 1294  
1591 1295 BR_PROPERTY(int, activeFrames, 100)
1592   - BR_PROPERTY(br::Idiocy::StreamModes, readMode, br::Idiocy::Auto)
  1296 + BR_PROPERTY(br::Idiocy::StreamModes, readMode, br::Idiocy::StreamGallery)
1593 1297 BR_PROPERTY(br::Transform*, endPoint, make("CollectOutput"))
1594 1298  
1595 1299 bool timeVarying() const { return true; }
... ...