reality augmented aruco opencv image-processing histogram

opencv - augmented - aruco marker



OpenCV dibujando un histograma 2D (1)

Me pregunto cómo trazar un histograma 2D de una estera HSV en opencv c ++. Mi código actual que intenta mostrarlo falla miserablemente. He examinado cómo trazar histogramas y todos los que he encontrado fueron aquellos que los trazaron como histogramas 1d independientes.

Aquí está mi salida actual con el número de contenedores de tono que son 30 y los contenedores de saturación que son 32:

Aquí hay otra salida con el número de contenedores de hue que son 7 y los contenedores de saturación son 5:

Me gustaría que se parezca más al resultado aquí

http://docs.opencv.org/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html

También me di cuenta cada vez que hago cout << Hist.size me da 50x50. ¿Debo entender que eso solo significa que la primera dimensión de la matriz tiene un tamaño de 250?

Además, ¿cómo se ordena el histograma de la frecuencia de valor más alta a la más baja (o viceversa)? Ese es otro problema que estoy tratando de resolver.

Mi función actual es la siguiente.

void Perform_Hist(Mat& MeanShift, Mat& Pyramid_Result, Mat& BackProj){ Mat HSV, Hist; int histSize[] = {hbins, sbins}; int channels[] = {0, 1}; float hranges[] = {0, 180}; float sranges[] = {0, 256}; const float* ranges[] = {hranges, sranges}; cvtColor(MeanShift, HSV, CV_BGR2HSV); Mat PyrGray = Pyramid_Result.clone(); calcHist(&HSV, 1, channels, Mat(), Hist, 2, histSize, ranges, true, false); normalize(Hist, Hist, 0, 255, NORM_MINMAX, -1, Mat()); invert(Hist, Hist, 1); calcBackProject(&PyrGray, 1, channels, Hist, BackProj, ranges, 1, true); double maxVal = 0; minMaxLoc(Hist, 0, &maxVal, 0, 0); int scale = 10; Mat histImage = Mat::zeros(sbins*scale, hbins*10, CV_8UC3); for(int i = 1; i < hbins * sbins; i++){ line(histImage, Point(hbins*sbins*(i-1), sbins - cvRound(Hist.at<float>(i-1))), Point(hbins*sbins*(i-1), sbins - cvRound(Hist.at<float>(i))), Scalar(255,0,0), 2, 8, 0); } imshow (HISTOGRAM, histImage); }


¿Querías decir algo como esto?

  • Es el histograma HSV mostrado como gráfico 3D
  • V se ignora para llegar a 3D (de lo contrario, sería un gráfico 4D ...)

en caso afirmativo, así es cómo hacerlo (no uso OpenCV, así que ajústelo a sus necesidades):

  1. convertir imagen de origen a HSV
  2. calcular el histograma ignorando el valor V
    • todos los colores con el mismo H, S se consideran de un solo color, sin importar cuál sea el V
    • puede ignorar cualquier otro, pero el parámetro V parece la mejor opción
  3. dibuja el gráfico

    • primer dibujo de elipse con color más oscuro (disco base HSV)
    • luego, para cada punto, tome el valor del histograma correspondiente y dibuje una línea vertical con un color más brillante. El tamaño de la línea es proporcional al valor del histograma.

Aquí está el código C ++ con el que hice esto:

picture pic0,pic1,pic2,zed; int his[65536]; DWORD w; int h,s,v,x,y,z,i,n; double r,a; color c; // compute histogram (ignore v) pic2=pic0; // copy input image pic0 to pic2 pic2.rgb2hsv(); // convert to HSV for (x=0;x<65536;x++) his[x]=0; // clear histogram for (y=0;y<pic2.ys;y++) // compute it for (x=0;x<pic2.xs;x++) { c=pic2.p[y][x]; h=c.db[picture::_h]; s=c.db[picture::_s]; w=h+(s<<8); // form 16 bit number from 24bit HSV color his[w]++; // update color usage count ... } for (n=0,x=0;x<65536;x++) if (n<his[x]) n=his[x]; // max probability // draw the colored HSV base plane and histogram zed =pic1; zed .clear(999); // zed buffer for 3D pic1.clear(0); // image of histogram for (h=0;h<255;h++) for (s=0;s<255;s++) { c.db[picture::_h]=h; c.db[picture::_s]=s; c.db[picture::_v]=100; // HSV base darker c.db[picture::_a]=0; x=pic1.xs>>1; // HSV base disc position centers on the bottom y=pic1.ys-100; a=2.0*M_PI*double(h)/256.0; // disc -> x,y r=double(s)/256.0; x+=120.0*r*cos(a); // elipse for 3D ilusion y+= 50.0*r*sin(a); z=-y; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x++; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y++; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x--; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y--; w=h+(s<<8); // get histogram index for this color i=((pic1.ys-150)*his[w])/n; c.db[picture::_v]=255; // histogram brighter for (;(i>0)&&(y>0);i--,y--) { if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x++; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y++; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x--; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y--; } } pic1.hsv2rgb(); // convert to RGB to see correct colors

  • la imagen de entrada es pic0 (rosa), la imagen de salida es pic1 (gráfico de histograma)
  • pic2 es el pic0 convertido a HSV para el cálculo del histograma
  • zed es el búfer Zed para la visualización en 3D evitando la clasificación Z ...

Utilizo mi propia clase de imagen para imágenes, por lo que algunos miembros son:

  • xs,ys tamaño de la imagen en píxeles
  • p[y][x].dd es un píxel en la posición (x, y) como tipo entero de 32 bits
  • clear(color) : borra toda la imagen
  • resize(xs,ys) : redimensiona la imagen a una nueva resolución
  • rgb2hsv() y hsv2rgb() ... adivina lo que hace :)

[edit1] tu histograma 2D

Parece que tienes un código de color en una matriz 2D. Un eje es H y el segundo es S Por lo tanto, debe calcular el valor H,S de la dirección de la matriz. Si es lineal, entonces para HSV[i][j] :

  • H=h0+(h1-h0)*i/maxi
  • S=s0+(s1-s0)*j/maxj
  • o i,j invertido
  • h0,h1,s0,s1 son los rangos de color
  • maxi,maxj son el tamaño de la matriz

Como puede ver, también descarta V como yo, así que ahora tiene H,S para cada celda en la matriz de histograma 2D. Donde probabilidad es el valor de la celda. Ahora, si desea dibujar una imagen, necesita saber cómo generarla (como un gráfico 2D, 3D, mapeo, ...). Para un gráfico 2D sin clasificar, dibuje un gráfico donde:

  • x=i+maj*i
  • y=HSV[i][j]
  • color=(H,S,V=200);

Si desea ordenarlo, simplemente calcule el eje x de manera diferente o realice un bucle de la matriz 2D en orden de clasificación yx simplemente incremente

[edit2] actualización de código y algunas imágenes

He reparado el código C ++ anterior (signo de valor Z incorrecto, cambiado la condición del búfer Z y agregado puntos más grandes para una salida más agradable). Sus colores de matriz 2D pueden ser así:

Donde un eje / índice es H , el otro S y el Value son fijos (elijo 200). Si sus ejes se intercambian, entonces simplemente duplíquelo con y=x , creo que ...

La clasificación de colores es realmente solo un orden en el que selecciona todos los colores de la matriz. por ejemplo:

v=200; x=0; for (h=0;h<256;h++) for (s=0;s<256;s++,x++) { y=HSV[h][s]; // here draw line (x,0)->(x,y) by color hsv2rgb(h,s,v); }

Esta es la forma incremental. Puede calcular x desde H,S lugar para lograr una clasificación diferente o intercambiar los fors ( x++ debe estar en el bucle interno)

Si desea trazar un histograma RGB, consulte:

  • cómo trazar el histograma de color rgb de la imagen con el objetivo c