Reading EXR file - winapi

I'm trying to create a IWICBitmap from an EXR file (error checks removed).
#pragma pack(push,1)
struct fl
{
float r, g, b, a;
};
#pragma pack(pop)
HRESULT Open(const char* f,IWICBitmap** d)
{
exr_context_initializer_t ctxtinit = EXR_DEFAULT_CONTEXT_INITIALIZER;
exr_context_t myfile = {};
exr_result_t rv = exr_start_read(&myfile, f, &ctxtinit);
int part_index = 0;
const exr_attr_chlist_t* chl = 0;
exr_get_channels(myfile, part_index, &chl);
int32_t ck = 0;
rv = exr_get_chunk_count(myfile, part_index, &ck);
int32_t sl = 0;
rv = exr_get_scanlines_per_chunk(myfile, part_index, &sl);
int y = 0;
int wi = 0;
int he = 0;
std::vector<fl> data; // put here the floats
exr_decode_pipeline_t dec = {};
for (int32_t cuk = 0; cuk < ck; cuk++)
{
exr_chunk_info_t ch = {};
exr_read_scanline_chunk_info(myfile, part_index, y, &ch);
wi = ch.width;
he += ch.height;
y += sl;
bool first = 0;
if (dec.decompress_fn == 0)
{
rv = exr_decoding_initialize(myfile, part_index, &ch, &dec);
rv = exr_decoding_choose_default_routines(myfile, part_index, &dec);
first = 1;
}
if (!first)
rv = exr_decoding_update(myfile, part_index,&ch,&dec);
rv = exr_decoding_run(myfile, part_index, &dec);
int NumPixels = (wi * ch.height);
auto BytesPerPixel = ch.unpacked_size / NumPixels;
if (true)
{
// RGB(A)
if (chl->entries[0].pixel_type == EXR_PIXEL_HALF)
{
if (BytesPerPixel == chl->num_channels * 2)
{
auto ds = data.size();
data.resize(ds + NumPixels);
auto p = data.data() + ds;
char* x = (char*)dec.unpacked_buffer;
for (int j = 0; j < NumPixels; j++)
{
uint16_t* u = (uint16_t*)x;
p->a = 1.0f;
for (int jH = 0; jH < chl->num_channels; jH++)
{
half ha(Imath_3_2::half::FromBits,*u);
ha.setBits(*u);
if (strcmp(chl->entries[jH].name.str, "R") == 0) p->r = ha.operator float();
if (strcmp(chl->entries[jH].name.str, "G") == 0) p->g = ha.operator float();
if (strcmp(chl->entries[jH].name.str, "B") == 0) p->b = ha.operator float();
if (strcmp(chl->entries[jH].name.str, "A") == 0) p->a = ha.operator float();
u++;
}
x += BytesPerPixel;
p++;
}
}
else
break;
}
if (chl->entries[0].pixel_type == EXR_PIXEL_FLOAT)
{
// code removed for simplicity, I guess the same issue happens here unless it's a problem of the half-float
}
}
}
rv = exr_decoding_destroy(myfile, &dec);
exr_finish(&myfile);
CComPtr<IWICImagingFactory2> wbfact = 0;
CoCreateInstance(CLSID_WICImagingFactory2, 0, CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2), (void**)&wbfact);
return wbfact->CreateBitmapFromMemory(wi, he, GUID_WICPixelFormat128bppPRGBAFloat, wi * 16,(UINT)data.size()*16, (BYTE*)data.data(), d);
}
What am I doing wrong? The pixel number I'm reading is correct (in this image 800x800).
My result:
Photoshop:
Is there a problem with the half-float? I'm just using the OpenEXR's IMath implementation.

Related

Digital Image Processing Contrast Stretching Histogram

Here I attach my code that I use to Draw the Histogram of the Contrasted image and also to convert a gray image into Contrast Image. Here I used low pint as 122 and highest point as 244. In the output histogram it reduce the height of the histogram.
I cannot find the error in my code
#include "opencv2/opencv.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
using namespace cv;
using namespace std;
int main(int argc, char* argv[]) {
Mat img = imread(argv[1], 1);
if (!img.data) {
cout << "Could not find the image!" << endl;
return -1;
}
int height = img.rows;
int width = img.cols;
int widthstep = img.step;
int ch = img.channels();
printf("Height : %d\n", height);
printf("Width : %d\n", width);
printf("Widthstep : %d\n", widthstep);
printf("No of channels : %d\n", ch);
Mat gray_image(height, width, CV_8UC1, Scalar(0));
cvtColor(img, gray_image, COLOR_BGR2GRAY);
Mat new_image = gray_image.clone();
int v;
int output{};
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int v = (int)gray_image.at<uchar>(y, x);
if (v >= 0 && v <= 122) {
output = int((6 / 122) * v);
}
else if (v > 100 && v <= 244) {
output = int(((244) / (122)) * (v - 122) + 6);
}
else if (v > 244 && v <= 255) {
output = int(((5) / (11)) * (v - 244) + 250);
}
new_image.at<uchar>(y, x) = (uchar)output;
}
}
int histn[256];
for (int i = 0; i < 256; i++) {
histn[i] = 0;
}
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
histn[(int)new_image.at<uchar>(y, x)] = histn[(int)new_image.at<uchar>(y, x)] + 1;
}
}
for (int i = 0; i < 256; i++) {
cout << i << ":" << histn[i] << endl;
}
int hist_wn = 512;
int hist_hn = 400;
int bin_wn = cvRound((double)hist_wn / 256);
Mat new_histogramImage(hist_hn, hist_wn, CV_8UC1, Scalar(255));
int maxn = histn[0];
for (int i = 0; i < 256; i++) {
if (maxn < histn[i]) {
maxn = histn[i];
}
}
for (int i = 0; i < 256; i++) {
histn[i] = ((double)histn[i] / maxn) * new_histogramImage.rows;
}
for (int i = 0; i < 256; i++) {
line(new_histogramImage, Point(bin_wn * (i), hist_hn), Point(bin_wn * (i), hist_hn - histn[i]), Scalar(0), 1, 8, 0);
}
imwrite("Gray_Image.png", gray_image);
imwrite("newcontrast_Image.png", new_image);
imwrite("Histogram.png", new_histogramImage);
namedWindow("Image");
imshow("Image", img);
namedWindow("Gray_Image");
imshow("Gray_Image", gray_image);
namedWindow("newcontrast_Image");
imshow("newcontrast_Image", new_image);
namedWindow("New_Histogram");
imshow("New_Histogram", new_histogramImage);
namedWindow("Old_Histogram");
imshow("Old_Histogram", histImage);
waitKey(0);
return 0;
}
Here are the new and old histograms that I got as outputs
I found the solution for the question. Here I changed the lowest and highest point values as 100 and 240 and when using the values set those as decimals values.
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int v = (int)gray_image.at<uchar>(y, x);
if (v >= 0 && v <= 100) {
output = int((5.0/ 100.0) * v);
}
else if (v > 100 && v <= 240) {
output = int(((245.0) / (140.0)) * (v - 100.0) + 5.0);
}
else if (v > 240 && v <= 255) {
output = int(((5.0) / (15.0)) * (v - 240.0) + 250.0);
}
new_image.at<uchar>(y, x) = (uchar)output;
}
}

Special minimum spanning tree

There is a node that can only get one line, I use both kruskal and prim, but the judger said TLE(Time Limit Exceed).
Then I will describe the question. There are many computers, we need to connect all of them, we give the cost of connection between different computers, also we give the special number of computer which can be only connected by one line. Finally, we guarantee there is a answer and there is no Self-Loop, but there may have multiple edge which have different weight between same node.
Here is my kruskal code, it's TLE.
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct edge{
int start;
int end;
int weight;
}Edge;
int special = 0;
int edgenum;
Edge _edge[600005];
int i, j, k;
int counter = 0;
bool Cmp(const edge &a, const edge &b){
return a.weight < b.weight;
}
int getEnd(int vends[], int i){
while(vends[i] != 0)
i = vends[i];
return i;
}
void kruskal(){
int p1, p2, m, n, ans = 0;
int vends[10005] = {0};
sort(_edge, _edge+counter, Cmp);
for(i = 0; i < edgenum; ++i){
p1 = _edge[i].start;
p2 = _edge[i].end;
if ((p1 == k || p2 == k) && special)
continue;
m = getEnd(vends, p1);
n = getEnd(vends, p2);
if(m != n){
if (p1 == k || p2 == k)
special = 1;
vends[m] = n;
ans += _edge[i].weight;
}
}
cout << ans << endl;
}
int main(){
int n, m;
cin >> n >> m >> k;
edgenum = m;
while(m--){
int a, b, c;
cin >> a >> b >> c;
_edge[counter].start = a; //Get the Edge
_edge[counter].weight = c;
_edge[counter++].end = b;
// _edge[counter].start = b;
// _edge[counter].weight = c;
// _edge[counter++].end = a;
}
kruskal();
}
Here is my Prim, but also TLE:
#include <iostream>
using namespace std;
typedef char VertexType;
typedef struct node{
int adjvex = 0;
int weight = INT32_MAX;
struct node *next = NULL;
}Node;
typedef struct vnode{
VertexType data;
Node *firstnode = NULL;
}Vnode;
Vnode node[10005];
int VNUM;
int n, m, k;
int lowcost[10005] = {0};
int addvnew[10005]; //未加入最小生成树表示为-1,加入则为0
int adjecent[10005] = {0};
bool is_special = false;
int flag;
void prim(int start){
long long sumweight = 0;
int i, j;
Node *p = node[start].firstnode;
for (i = 1; i <= VNUM; ++i) { //重置
addvnew[i] = -1;
}
while (p->next != NULL){
if (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])
lowcost[p->adjvex] = p->weight;
p = p->next;
}
if (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])
lowcost[p->adjvex] = p->weight;
addvnew[start] = 0;
// adjecent[start] = start;
if (start == k) {
is_special = true;
flag = 1;
}
for (i = 1; i < VNUM; ++i) {
int min = INT32_MAX;
int v=-1;
for (j = 1; j <= VNUM; ++j) { //Find the min
if (addvnew[j] == -1 && lowcost[j] < min && lowcost[j] != 0){
min = lowcost[j];
v = j;
}
}
if (v != -1){ //if min is found
if (flag == 1){
for (int l = 0; l < 10005; ++l) {
lowcost[l] = 0;
}
flag = 0;
}
addvnew[v] = 0;
sumweight += min;
p = node[v].firstnode;
while(p->next != NULL){
if (is_special && p->adjvex == k){ //If find the special node
p = p->next;
continue;
}
if(addvnew[p->adjvex] == -1 && (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])){ //如果该点未连接
lowcost[p->adjvex] = p->weight;
}
p = p->next;
}
if (!(is_special && p->adjvex == k))
if(addvnew[p->adjvex] == -1 && (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])){
lowcost[p->adjvex] = p->weight;
}
}
}
cout << sumweight << endl;
}
int main(){
cin >> n >> m >> k;
VNUM = n;
while (m--){
int a, b, c;
cin >> a >> b >> c;
Node *p = (Node*)malloc(sizeof(Node));
p->adjvex = b;
p->weight = c;
p->next = node[a].firstnode;
node[a].firstnode = p;
Node *q = (Node*)malloc(sizeof(Node));
q->adjvex = a;
q->weight = c;
q->next = node[b].firstnode;
node[b].firstnode = q;
}
prim(k);
}
I don't know how to modify the both code, I try my best, thank you

Processing Image data changes during save

I'm trying to create a program to hide data in a image file. Data bits are hidden into last bit of every pixels blue value. First four pixels contain the length of following data bytes.
Everything works fine when I encrypt the data to image and then decrypt it without saving the image in between. However if I encrypt the data to an image and then save it and then open the file again and try to decrypt it, decryption fails since the values seem to have changed.
I wonder if there is something similar happening as with txt files where there is BOM containing byte order data prepended into the file?
The code works if I change the color c = crypted.pixels[pos + i];
to color c = original.pixels[pos + i]; in readByteAt function
and run the encrypting function first and then the decryption function.
This causes the code to run the decryption function on the just encrypted image still in program memory instead reading it from the file.
Any ideas on what causes this or how to prevent it are welcome!
here is the full (messy) code:
PImage original;
PImage crypted;
int imagesize;
boolean ready = false;
void setup() {
size(100, 100);
imagesize = width * height;
}
void draw() {
}
void encrypt()
{
original = loadImage("image.jpg");
original.loadPixels();
println("begin encrypt");
int pos = 0;
byte b[] = loadBytes("DATA.txt");
println("encrypting in image...");
int len = b.length;
println("len " + len);
writeByteAt((len >> (3*8)) & 0xFF, 0);
writeByteAt((len >> (2*8)) & 0xFF, 8);
writeByteAt((len >> (1*8)) & 0xFF, 16);
writeByteAt(len & 0xFF, 24);
pos = 32;
for (int i = 3; i < b.length; i++) {
int a = b[i] & 0xff;
print(char(a));
writeByteAt(a, pos);
pos += 8;
}
original.updatePixels();
println();
println("done");
original.save("encrypted.jpg");
}
void writeByteAt(int b, int pos)
{
println("writing " + b + " at " + pos);
for (int i = 0; i < 8; i++)
{
color c = original.pixels[pos + i];
int v = int(blue(c));
if ((b & (1 << i)) > 0)
{
v = v | 1;
} else
{
v = v & 0xFE;
}
original.pixels[pos+i] = color(red(c), green(c), v);
//original.pixels[pos+i] = color(255,255,255);
}
}
int readByteAt(int pos)
{
int b = 0;
for (int i = 0; i < 8; i++)
{
color c = crypted.pixels[pos + i];
int v = int(blue(c));
if ((v & 1) > 0)
{
b += (1 << i);
}
}
return b;
}
void decrypt()
{
crypted = loadImage("encrypted.jpg");
crypted.loadPixels();
println("begin decrypt");
int pos = 0;
PrintWriter output = createWriter("out.txt");
println("decrypting...");
int len = 0;
len += readByteAt(0) << 3*8;
len += readByteAt(8) << 2*8;
len += readByteAt(16) << 1*8;
len += readByteAt(24);
pos = 32;
if(len >= imagesize)
{
println("ERROR: DATA LENGTH OVER IMAGE SIZE");
return;
}
println(len);
while (pos < ((len+1)*8)) {
output.print(char(readByteAt(pos)));
print(char(readByteAt(pos)));
pos += 8;
}
output.flush(); // Writes the remaining data to the file
output.close();
println("\nDone");
}
void keyPressed()
{
if(key == 'e')
{
encrypt();
}
if(key == 'd')
{
decrypt();
}
}

How to modify algorithm to get all maximal matchings in bipartite graph?

I use the following code to find maximal matching in bipartite graph
(I've tried to add a few comments):
#include <iostream>
using namespace std;
// definition of lists elements
//-------------------------------
struct slistEl
{
slistEl * next;
int data;
};
// definition objective type queue
//---------------------------------
class queue
{
private:
slistEl * head;
slistEl * tail;
public:
queue();
~queue();
bool empty(void);
int front(void);
void push(int v);
void pop(void);
};
queue::queue()
{
head = tail = NULL;
}
queue::~queue()
{
while(head) pop();
}
bool queue::empty(void)
{
return !head;
}
int queue::front(void)
{
if(head) return head->data;
else return -10000;
}
void queue::push(int v)
{
slistEl * p = new slistEl;
p->next = NULL;
p->data = v;
if(tail) tail->next = p;
else head = p;
tail = p;
}
void queue::pop(void)
{
if(head)
{
slistEl * p = head;
head = head->next;
if(!head) tail = NULL;
delete p;
}
}
//---------------
// main part
//---------------
queue Q; // queue
int *Color; // colors of vertexes
slistEl **graf; // adjacency array
int **C; // matrix of capacity
int **F; // matrix of nett flow
int *P; // array of prev
int *CFP; // array of residual capacity
int n,m,fmax,cp,v,u,i,j; //
bool esc; //
slistEl *pr, *rr; // pointer for list elements
int main(int argc, char *argv[])
{
// n - number of vertexes
// m - number of edges
cin >> n >> m;
Color = new int [n];
graf = new slistEl * [n];
for(i = 0; i < n; i++)
{
graf[i] = NULL;
Color[i] = 0;
}
C = new int * [n+2];
F = new int * [n+2];
for(i = 0; i <= n + 1; i++)
{
C[i] = new int [n+2];
F[i] = new int [n+2];
for(j = 0; j <= n + 1; j++)
{
C[i][j] = 0;
F[i][j] = 0;
}
}
P = new int [n+2];
CFP = new int [n+2];
// reading edges definition and adding to adjacency list
for(i = 0; i < m; i++)
{
cin >> v >> u;
pr = new slistEl;
pr->data = u;
pr->next = graf[v];
graf[v] = pr;
pr = new slistEl;
pr->data = v;
pr->next = graf[u];
graf[u] = pr;
}
for(i = 0; i < n; i++){
cin>> Color[i];
}
for(i = 0; i < n; i++)
if(Color[i] == -1)
{
for(pr = graf[i]; pr; pr = pr -> next) // neighbours of blue
C[i][pr->data] = 1; // capacity to red
C[n][i] = 1; // capacity to source
}
else C[i][n+1] = 1; // capacity edges to outfall
//** Edmonds-Karp algorithm **
fmax = 0;
while(true)
{
for(i = 0; i <= n + 1; i++) P[i] = -1;
P[n] = -2;
CFP[n] = MAXINT;
while(!Q.empty()) Q.pop();
Q.push(n);
esc = false;
while(!Q.empty())
{
v = Q.front(); Q.pop();
for(u = 0; u <= n + 1; u++)
{
cp = C[v][u] - F[v][u];
if(cp && (P[u] == -1))
{
P[u] = v;
if(CFP[v] > cp) CFP[u] = cp; else CFP[u] = CFP[v];
if(u == n+1)
{
fmax += CFP[n+1];
i = u;
while(i != n)
{
v = P[i];
F[v][i] += CFP[n+1];
F[i][v] -= CFP[n+1];
i = v;
}
esc = true; break;
}
Q.push(u);
}
}
if(esc) break;
}
if(!esc) break;
}
// showing reuslts
if(fmax > 0)
for(v = 0; v < n; v++)
for(u = 0; u < n; u++)
if((C[v][u] == 1) && (F[v][u] == 1))
cout << v << " - " << u << endl;
cout << endl;
// cleaning
delete [] Color;
for(i = 0; i < n; i++)
{
pr = graf[i];
while(pr)
{
rr = pr;
pr = pr->next;
delete rr;
}
}
delete [] graf;
for(i = 0; i <= n + 1; i++)
{
delete [] C[i];
delete [] F[i];
}
delete [] C;
delete [] F;
delete [] P;
delete [] CFP;
return 0;
}
It returns only one maximal matching. For example for data:
6 7
0 3 0 5
1 3 1 4 1 5
2 3 2 5
1 1 1 -1 -1 -1
But there are more maximal matchings.
I don't know, how should I modify it to get all results and I would like to ask somebody for help. Thank you in advance.
That algorithm is only efficient to get you a maximum matching.
If you want all maximal matching you have to consider the case where any matching is a maximal matching. In that case you have N! possibilities.
Since you will need to visit all solutions your complexity will be O(N!) at least. Therefore, forget the code you have, you can just try all possible matchings using a recursive algorithm and keep the set of maximal matching you get.

OpenCV Stereo matching and disparity map

I am using the code sample for stereo matching that came with openCV source code, here:
/*
* stereo_match.cpp
* calibration
*
* Created by Victor Eruhimov on 1/18/10.
* Copyright 2010 Argus Corp. All rights reserved.
*
*/
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include <stdio.h>
using namespace cv;
static void print_help()
{
printf("\nDemo stereo matching converting L and R images into disparity and point clouds\n");
printf("\nUsage: stereo_match <left_image> <right_image> [--algorithm=bm|sgbm|hh|var] [--blocksize=<block_size>]\n"
"[--max-disparity=<max_disparity>] [--scale=scale_factor>] [-i <intrinsic_filename>] [-e <extrinsic_filename>]\n"
"[--no-display] [-o <disparity_image>] [-p <point_cloud_file>]\n");
}
static void saveXYZ(const char* filename, const Mat& mat)
{
const double max_z = 1.0e4;
FILE* fp = fopen(filename, "wt");
for(int y = 0; y < mat.rows; y++)
{
for(int x = 0; x < mat.cols; x++)
{
Vec3f point = mat.at<Vec3f>(y, x);
if(fabs(point[2] - max_z) < FLT_EPSILON || fabs(point[2]) > max_z) continue;
fprintf(fp, "%f %f %f\n", point[0], point[1], point[2]);
}
}
fclose(fp);
}
int main(int argc, char** argv)
{
const char* algorithm_opt = "--algorithm=";
const char* maxdisp_opt = "--max-disparity=";
const char* blocksize_opt = "--blocksize=";
const char* nodisplay_opt = "--no-display=";
const char* scale_opt = "--scale=";
if(argc < 3)
{
print_help();
return 0;
}
const char* img1_filename = 0;
const char* img2_filename = 0;
const char* intrinsic_filename = 0;
const char* extrinsic_filename = 0;
const char* disparity_filename = 0;
const char* point_cloud_filename = 0;
enum { STEREO_BM=0, STEREO_SGBM=1, STEREO_HH=2, STEREO_VAR=3 };
int alg = STEREO_SGBM;
int SADWindowSize = 0, numberOfDisparities = 0;
bool no_display = false;
float scale = 1.f;
StereoBM bm;
StereoSGBM sgbm;
StereoVar var;
for( int i = 1; i < argc; i++ )
{
if( argv[i][0] != '-' )
{
if( !img1_filename )
img1_filename = argv[i];
else
img2_filename = argv[i];
}
else if( strncmp(argv[i], algorithm_opt, strlen(algorithm_opt)) == 0 )
{
char* _alg = argv[i] + strlen(algorithm_opt);
alg = strcmp(_alg, "bm") == 0 ? STEREO_BM :
strcmp(_alg, "sgbm") == 0 ? STEREO_SGBM :
strcmp(_alg, "hh") == 0 ? STEREO_HH :
strcmp(_alg, "var") == 0 ? STEREO_VAR : -1;
if( alg < 0 )
{
printf("Command-line parameter error: Unknown stereo algorithm\n\n");
print_help();
return -1;
}
}
else if( strncmp(argv[i], maxdisp_opt, strlen(maxdisp_opt)) == 0 )
{
if( sscanf( argv[i] + strlen(maxdisp_opt), "%d", &numberOfDisparities ) != 1 ||
numberOfDisparities < 1 || numberOfDisparities % 16 != 0 )
{
printf("Command-line parameter error: The max disparity (--maxdisparity=<...>) must be a positive integer divisible by 16\n");
print_help();
return -1;
}
}
else if( strncmp(argv[i], blocksize_opt, strlen(blocksize_opt)) == 0 )
{
if( sscanf( argv[i] + strlen(blocksize_opt), "%d", &SADWindowSize ) != 1 ||
SADWindowSize < 1 || SADWindowSize % 2 != 1 )
{
printf("Command-line parameter error: The block size (--blocksize=<...>) must be a positive odd number\n");
return -1;
}
}
else if( strncmp(argv[i], scale_opt, strlen(scale_opt)) == 0 )
{
if( sscanf( argv[i] + strlen(scale_opt), "%f", &scale ) != 1 || scale < 0 )
{
printf("Command-line parameter error: The scale factor (--scale=<...>) must be a positive floating-point number\n");
return -1;
}
}
else if( strcmp(argv[i], nodisplay_opt) == 0 )
no_display = true;
else if( strcmp(argv[i], "-i" ) == 0 )
intrinsic_filename = argv[++i];
else if( strcmp(argv[i], "-e" ) == 0 )
extrinsic_filename = argv[++i];
else if( strcmp(argv[i], "-o" ) == 0 )
disparity_filename = argv[++i];
else if( strcmp(argv[i], "-p" ) == 0 )
point_cloud_filename = argv[++i];
else
{
printf("Command-line parameter error: unknown option %s\n", argv[i]);
return -1;
}
}
if( !img1_filename || !img2_filename )
{
printf("Command-line parameter error: both left and right images must be specified\n");
return -1;
}
if( (intrinsic_filename != 0) ^ (extrinsic_filename != 0) )
{
printf("Command-line parameter error: either both intrinsic and extrinsic parameters must be specified, or none of them (when the stereo pair is already rectified)\n");
return -1;
}
if( extrinsic_filename == 0 && point_cloud_filename )
{
printf("Command-line parameter error: extrinsic and intrinsic parameters must be specified to compute the point cloud\n");
return -1;
}
int color_mode = alg == STEREO_BM ? 0 : -1;
Mat img1 = imread(img1_filename, color_mode);
Mat img2 = imread(img2_filename, color_mode);
if( scale != 1.f )
{
Mat temp1, temp2;
int method = scale < 1 ? INTER_AREA : INTER_CUBIC;
resize(img1, temp1, Size(), scale, scale, method);
img1 = temp1;
resize(img2, temp2, Size(), scale, scale, method);
img2 = temp2;
}
Size img_size = img1.size();
Rect roi1, roi2;
Mat Q;
if( intrinsic_filename )
{
// reading intrinsic parameters
FileStorage fs(intrinsic_filename, CV_STORAGE_READ);
if(!fs.isOpened())
{
printf("Failed to open file %s\n", intrinsic_filename);
return -1;
}
Mat M1, D1, M2, D2;
fs["M1"] >> M1;
fs["D1"] >> D1;
fs["M2"] >> M2;
fs["D2"] >> D2;
M1 *= scale;
M2 *= scale;
fs.open(extrinsic_filename, CV_STORAGE_READ);
if(!fs.isOpened())
{
printf("Failed to open file %s\n", extrinsic_filename);
return -1;
}
Mat R, T, R1, P1, R2, P2;
fs["R"] >> R;
fs["T"] >> T;
stereoRectify( M1, D1, M2, D2, img_size, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, -1, img_size, &roi1, &roi2 );
Mat map11, map12, map21, map22;
initUndistortRectifyMap(M1, D1, R1, P1, img_size, CV_16SC2, map11, map12);
initUndistortRectifyMap(M2, D2, R2, P2, img_size, CV_16SC2, map21, map22);
Mat img1r, img2r;
remap(img1, img1r, map11, map12, INTER_LINEAR);
remap(img2, img2r, map21, map22, INTER_LINEAR);
img1 = img1r;
img2 = img2r;
}
numberOfDisparities = numberOfDisparities > 0 ? numberOfDisparities : ((img_size.width/8) + 15) & -16;
bm.state->roi1 = roi1;
bm.state->roi2 = roi2;
bm.state->preFilterCap = 31;
bm.state->SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 9;
bm.state->minDisparity = 0;
bm.state->numberOfDisparities = numberOfDisparities;
bm.state->textureThreshold = 10;
bm.state->uniquenessRatio = 15;
bm.state->speckleWindowSize = 100;
bm.state->speckleRange = 32;
bm.state->disp12MaxDiff = 1;
sgbm.preFilterCap = 63;
sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;
int cn = img1.channels();
sgbm.P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
sgbm.minDisparity = 0;
sgbm.numberOfDisparities = numberOfDisparities;
sgbm.uniquenessRatio = 10;
sgbm.speckleWindowSize = bm.state->speckleWindowSize;
sgbm.speckleRange = bm.state->speckleRange;
sgbm.disp12MaxDiff = 1;
sgbm.fullDP = alg == STEREO_HH;
var.levels = 3; // ignored with USE_AUTO_PARAMS
var.pyrScale = 0.5; // ignored with USE_AUTO_PARAMS
var.nIt = 25;
var.minDisp = -numberOfDisparities;
var.maxDisp = 0;
var.poly_n = 3;
var.poly_sigma = 0.0;
var.fi = 15.0f;
var.lambda = 0.03f;
var.penalization = var.PENALIZATION_TICHONOV; // ignored with USE_AUTO_PARAMS
var.cycle = var.CYCLE_V; // ignored with USE_AUTO_PARAMS
var.flags = var.USE_SMART_ID | var.USE_AUTO_PARAMS | var.USE_INITIAL_DISPARITY | var.USE_MEDIAN_FILTERING ;
Mat disp, disp8;
//Mat img1p, img2p, dispp;
//copyMakeBorder(img1, img1p, 0, 0, numberOfDisparities, 0, IPL_BORDER_REPLICATE);
//copyMakeBorder(img2, img2p, 0, 0, numberOfDisparities, 0, IPL_BORDER_REPLICATE);
int64 t = getTickCount();
if( alg == STEREO_BM )
bm(img1, img2, disp);
else if( alg == STEREO_VAR ) {
var(img1, img2, disp);
}
else if( alg == STEREO_SGBM || alg == STEREO_HH )
sgbm(img1, img2, disp);
t = getTickCount() - t;
printf("Time elapsed: %fms\n", t*1000/getTickFrequency());
//disp = dispp.colRange(numberOfDisparities, img1p.cols);
if( alg != STEREO_VAR )
disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.));
else
disp.convertTo(disp8, CV_8U);
if( !no_display )
{
namedWindow("left", 1);
imshow("left", img1);
namedWindow("right", 1);
imshow("right", img2);
namedWindow("disparity", 0);
imshow("disparity", disp8);
printf("press any key to continue...");
fflush(stdout);
waitKey();
printf("\n");
}
if(disparity_filename)
imwrite(disparity_filename, disp8);
if(point_cloud_filename)
{
printf("storing the point cloud...");
fflush(stdout);
Mat xyz;
reprojectImageTo3D(disp, xyz, Q, true);
saveXYZ(point_cloud_filename, xyz);
printf("\n");
}
return 0;
}
And I have tried all of the algorithms on the following set of images:
http://imageshack.com/a/img607/4641/utam.jpg (left)
http://imageshack.com/a/img62/5939/2hkc.jpg (right)
Here is my result:
http://imageshack.com/a/img856/4274/1n50.jpg
And here is the desired result:
http://i.stack.imgur.com/W9PBr.jpg
What could be the problem?
change parameters! For example, say bm, my experience is SADWindowSize and minDisparity really matters a lot! so you can add trackbars for each parameter and play with it until you get desired result. I've tried the same pair of images and it works fine. So all you need to do it try, try and try parameters.
I know it sounds crazy, but I had similar output when I was accidentally passing the same image as both the left and right input to the SGBMStereo algorithm. Just taking a shot in the dark...

Resources