Remove ghost removal
This commit is contained in:
parent
89508bf7ab
commit
b1af5cc478
@ -288,63 +288,6 @@ public:
|
||||
|
||||
CV_EXPORTS_W Ptr<MergeRobertson> createMergeRobertson();
|
||||
|
||||
class CV_EXPORTS_W Ghostbuster : public Algorithm
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, std::vector<float>& times, Mat response) = 0;
|
||||
};
|
||||
|
||||
// "Ghost Detection and Removal in High Dynamic Range Images", Sidibe et al., 2009
|
||||
|
||||
class CV_EXPORTS_W GhostbusterOrder : public Ghostbuster
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, std::vector<float>& times, Mat response) = 0;
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0;
|
||||
|
||||
CV_WRAP virtual int getUnderexp() = 0;
|
||||
CV_WRAP virtual void setUnderexp(int value) = 0;
|
||||
|
||||
CV_WRAP virtual int getOverexp() = 0;
|
||||
CV_WRAP virtual void setOverexp(int value) = 0;
|
||||
};
|
||||
|
||||
CV_EXPORTS_W Ptr<GhostbusterOrder> createGhostbusterOrder(int underexp = 20, int overexp = 240);
|
||||
|
||||
// "Fast and Robust High Dynamic Range Image Generation with Camera and Object Movement", Grosch, 2006
|
||||
|
||||
class CV_EXPORTS_W GhostbusterPredict : public Ghostbuster
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, std::vector<float>& times, Mat response) = 0;
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, std::vector<float>& times) = 0;
|
||||
|
||||
CV_WRAP virtual int getThreshold() = 0;
|
||||
CV_WRAP virtual void setThreshold(int value) = 0;
|
||||
|
||||
CV_WRAP virtual int getUnderexp() = 0;
|
||||
CV_WRAP virtual void setUnderexp(int value) = 0;
|
||||
|
||||
CV_WRAP virtual int getOverexp() = 0;
|
||||
CV_WRAP virtual void setOverexp(int value) = 0;
|
||||
};
|
||||
|
||||
CV_EXPORTS_W Ptr<GhostbusterPredict> createGhostbusterPredict(int thresh = 10, int underexp = 20, int overexp = 240);
|
||||
|
||||
// "Bitmap Movement Detection: HDR for Dynamic Scenes", Pece, Kautz, 2010
|
||||
|
||||
class CV_EXPORTS_W GhostbusterBitmap : public Ghostbuster
|
||||
{
|
||||
public:
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, std::vector<float>& times, Mat response) = 0;
|
||||
CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0;
|
||||
|
||||
CV_WRAP virtual int getExclude() = 0;
|
||||
CV_WRAP virtual void setExclude(int value) = 0;
|
||||
};
|
||||
|
||||
CV_EXPORTS_W Ptr<GhostbusterBitmap> createGhostbusterBitmap(int exclude = 4);
|
||||
|
||||
} // cv
|
||||
|
||||
#endif
|
||||
|
@ -263,284 +263,5 @@ Ptr<AlignMTB> createAlignMTB(int max_bits, int exclude_range, bool cut)
|
||||
return new AlignMTBImpl(max_bits, exclude_range, cut);
|
||||
}
|
||||
|
||||
class floatIndexCmp {
|
||||
public:
|
||||
floatIndexCmp(std::vector<float> data) :
|
||||
data(data)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator() (int i,int j)
|
||||
{
|
||||
return data[i] < data[j];
|
||||
}
|
||||
protected:
|
||||
std::vector<float> data;
|
||||
};
|
||||
|
||||
class GhostbusterOrderImpl : public GhostbusterOrder
|
||||
{
|
||||
public:
|
||||
GhostbusterOrderImpl(int underexp, int overexp) :
|
||||
underexp(underexp),
|
||||
overexp(overexp),
|
||||
name("GhostbusterOrder")
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst, std::vector<float>& times, Mat response)
|
||||
{
|
||||
process(src, dst);
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst)
|
||||
{
|
||||
std::vector<Mat> unsorted_images;
|
||||
src.getMatVector(unsorted_images);
|
||||
checkImageDimensions(unsorted_images);
|
||||
|
||||
std::vector<Mat> images;
|
||||
sortImages(unsorted_images, images);
|
||||
|
||||
int channels = images[0].channels();
|
||||
dst.create(images[0].size(), CV_8U);
|
||||
|
||||
Mat res = Mat::zeros(images[0].size(), CV_8U);
|
||||
|
||||
std::vector<Mat> splitted(channels);
|
||||
split(images[0], splitted);
|
||||
for(size_t i = 0; i < images.size() - 1; i++) {
|
||||
|
||||
std::vector<Mat> next_splitted(channels);
|
||||
split(images[i + 1], next_splitted);
|
||||
|
||||
for(int c = 0; c < channels; c++) {
|
||||
Mat exposed = (splitted[c] >= underexp) & (splitted[c] <= overexp);
|
||||
exposed &= (next_splitted[c] >= underexp) & (next_splitted[c] <= overexp);
|
||||
Mat ghost = (splitted[c] > next_splitted[c]) & exposed;
|
||||
res |= ghost;
|
||||
}
|
||||
splitted = next_splitted;
|
||||
}
|
||||
res.copyTo(dst.getMat());
|
||||
}
|
||||
|
||||
int getUnderexp() {return underexp;}
|
||||
void setUnderexp(int value) {underexp = value;}
|
||||
|
||||
int getOverexp() {return overexp;}
|
||||
void setOverexp(int value) {overexp = value;}
|
||||
|
||||
void write(FileStorage& fs) const
|
||||
{
|
||||
fs << "name" << name
|
||||
<< "overexp" << overexp
|
||||
<< "underexp" << underexp;
|
||||
}
|
||||
|
||||
void read(const FileNode& fn)
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
overexp = fn["overexp"];
|
||||
underexp = fn["underexp"];
|
||||
}
|
||||
|
||||
protected:
|
||||
int overexp, underexp;
|
||||
String name;
|
||||
|
||||
void sortImages(std::vector<Mat>& images, std::vector<Mat>& sorted)
|
||||
{
|
||||
std::vector<int>indices(images.size());
|
||||
std::vector<float>means(images.size());
|
||||
for(size_t i = 0; i < images.size(); i++) {
|
||||
indices[i] = i;
|
||||
means[i] = mean(mean(images[i]))[0];
|
||||
}
|
||||
sort(indices.begin(), indices.end(), floatIndexCmp(means));
|
||||
sorted.resize(images.size());
|
||||
for(size_t i = 0; i < images.size(); i++) {
|
||||
sorted[i] = images[indices[i]];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<GhostbusterOrder> createGhostbusterOrder(int underexp, int overexp)
|
||||
{
|
||||
return new GhostbusterOrderImpl(underexp, overexp);
|
||||
}
|
||||
|
||||
class GhostbusterPredictImpl : public GhostbusterPredict
|
||||
{
|
||||
public:
|
||||
GhostbusterPredictImpl(int thresh, int underexp, int overexp) :
|
||||
thresh(thresh),
|
||||
underexp(underexp),
|
||||
overexp(overexp),
|
||||
name("GhostbusterPredict")
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst, std::vector<float>& times, Mat response)
|
||||
{
|
||||
std::vector<Mat> images;
|
||||
src.getMatVector(images);
|
||||
checkImageDimensions(images);
|
||||
|
||||
int channels = images[0].channels();
|
||||
dst.create(images[0].size(), CV_8U);
|
||||
|
||||
Mat res = Mat::zeros(images[0].size(), CV_8U);
|
||||
|
||||
Mat radiance;
|
||||
LUT(images[0], response, radiance);
|
||||
std::vector<Mat> splitted(channels);
|
||||
split(radiance, splitted);
|
||||
std::vector<Mat> resp_split(channels);
|
||||
split(response, resp_split);
|
||||
for(size_t i = 0; i < images.size() - 1; i++) {
|
||||
|
||||
std::vector<Mat> next_splitted(channels);
|
||||
LUT(images[i + 1], response, radiance);
|
||||
split(radiance, next_splitted);
|
||||
|
||||
for(int c = 0; c < channels; c++) {
|
||||
|
||||
Mat predicted = splitted[c] / times[i] * times[i + 1];
|
||||
|
||||
Mat low = max(thresh, next_splitted[c]) - thresh;
|
||||
Mat high = min(255 - thresh, next_splitted[c]) + thresh;
|
||||
low.convertTo(low, CV_8U);
|
||||
high.convertTo(high, CV_8U);
|
||||
LUT(low, resp_split[c], low);
|
||||
LUT(high, resp_split[c], high);
|
||||
|
||||
Mat exposed = (splitted[c] >= underexp) & (splitted[c] <= overexp);
|
||||
exposed &= (next_splitted[c] >= underexp) & (next_splitted[c] <= overexp);
|
||||
|
||||
Mat ghost = (low < predicted) & (predicted < high);
|
||||
ghost &= exposed;
|
||||
res |= ghost;
|
||||
}
|
||||
splitted = next_splitted;
|
||||
}
|
||||
res.copyTo(dst.getMat());
|
||||
}
|
||||
|
||||
virtual void process(InputArrayOfArrays src, OutputArray dst, std::vector<float>& times)
|
||||
{
|
||||
Mat response = linearResponse(3);
|
||||
response.at<Vec3f>(0) = response.at<Vec3f>(1);
|
||||
process(src, dst, times, response);
|
||||
}
|
||||
|
||||
CV_WRAP virtual int getThreshold() {return thresh;}
|
||||
CV_WRAP virtual void setThreshold(int value) {thresh = value;}
|
||||
|
||||
int getUnderexp() {return underexp;}
|
||||
void setUnderexp(int value) {underexp = value;}
|
||||
|
||||
int getOverexp() {return overexp;}
|
||||
void setOverexp(int value) {overexp = value;}
|
||||
|
||||
void write(FileStorage& fs) const
|
||||
{
|
||||
fs << "name" << name
|
||||
<< "overexp" << overexp
|
||||
<< "underexp" << underexp
|
||||
<< "thresh" << thresh;
|
||||
}
|
||||
|
||||
void read(const FileNode& fn)
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
overexp = fn["overexp"];
|
||||
underexp = fn["underexp"];
|
||||
thresh = fn["thresh"];
|
||||
}
|
||||
|
||||
protected:
|
||||
int thresh, underexp, overexp;
|
||||
String name;
|
||||
};
|
||||
|
||||
Ptr<GhostbusterPredict> createGhostbusterPredict(int thresh, int underexp, int overexp)
|
||||
{
|
||||
return new GhostbusterPredictImpl(thresh, underexp, overexp);
|
||||
}
|
||||
|
||||
class GhostbusterBitmapImpl : public GhostbusterBitmap
|
||||
{
|
||||
public:
|
||||
GhostbusterBitmapImpl(int exclude) :
|
||||
exclude(exclude),
|
||||
name("GhostbusterBitmap")
|
||||
{
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst, std::vector<float>& times, Mat response)
|
||||
{
|
||||
process(src, dst);
|
||||
}
|
||||
|
||||
void process(InputArrayOfArrays src, OutputArray dst)
|
||||
{
|
||||
std::vector<Mat> images;
|
||||
src.getMatVector(images);
|
||||
checkImageDimensions(images);
|
||||
|
||||
int channels = images[0].channels();
|
||||
dst.create(images[0].size(), CV_8U);
|
||||
|
||||
Mat res = Mat::zeros(images[0].size(), CV_8U);
|
||||
|
||||
Ptr<AlignMTB> MTB = createAlignMTB();
|
||||
MTB->setExcludeRange(exclude);
|
||||
|
||||
for(size_t i = 0; i < images.size(); i++) {
|
||||
Mat gray;
|
||||
if(channels == 1) {
|
||||
gray = images[i];
|
||||
} else {
|
||||
cvtColor(images[i], gray, COLOR_RGB2GRAY);
|
||||
}
|
||||
|
||||
Mat tb, eb;
|
||||
MTB->computeBitmaps(gray, tb, eb);
|
||||
tb &= eb & 1;
|
||||
res += tb;
|
||||
}
|
||||
res = (res > 0) & (res < images.size());
|
||||
res.copyTo(dst.getMat());
|
||||
}
|
||||
|
||||
int getExclude() {return exclude;}
|
||||
void setExclude(int value) {exclude = value;}
|
||||
|
||||
void write(FileStorage& fs) const
|
||||
{
|
||||
fs << "name" << name
|
||||
<< "exclude" << exclude;
|
||||
}
|
||||
|
||||
void read(const FileNode& fn)
|
||||
{
|
||||
FileNode n = fn["name"];
|
||||
CV_Assert(n.isString() && String(n) == name);
|
||||
exclude = fn["exclude"];
|
||||
}
|
||||
|
||||
protected:
|
||||
int exclude;
|
||||
String name;
|
||||
};
|
||||
|
||||
Ptr<GhostbusterBitmap> createGhostbusterBitmap(int exclude)
|
||||
{
|
||||
return new GhostbusterBitmapImpl(exclude);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user