I want to create a table, my code in QtCreator:
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableWidget->setColumnCount(5);
ui->tableWidget->setHorizontalHeaderLabels(QStringList() << tr("First") << tr("Second") << tr("Third") << tr("Fourth") << tr("Fifth"));
ui->tableWidget->setColumnWidth(0, 80);
ui->tableWidget->setColumnWidth(1, 140);
ui->tableWidget->setColumnWidth(2, 80);
ui->tableWidget->setColumnWidth(3, 140);
ui->tableWidget->setStyleSheet("QHeaderView::section { background-color: rgb(217,217,217)}");
ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
for (int c = 0; c < ui->tableWidget->horizontalHeader()->count(); c++) {
ui->tableWidget->horizontalHeaderItem(c)->setSizeHint(QSize(0, 50));
}
for (int j = 0; j < ui->tableWidget->columnCount(); j++) {
QTableWidgetItem *item = new QTableWidgetItem;
if ((j == 0) || (j == 3) || (j == 4)) {
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
}
if (j!=0) {
item->setTextAlignment(Qt::AlignCenter);
}
ui->tableWidget->setItem(0, j, item);
}
There is only one row in the table, I do it with Designer, so there is no line for the number of row in my code above.
Result:
With the same code above, I do in Visual Studio and receive this table:
The height of row with VS is the height of the table, which is too large. How can I receive the small row as in QtCreator ?
Related
I am using the Hough transform algorithm do determine lines.
Right now I am just taking the peak values from the matrix that are over a certain threshold, but I am getting a lot of duplicate lines that i want to merge into one.
This is the code for finding peaks:
int prevVal = INT_MIN;
const int NOISE = 110;
enum
{
Ascending,
Descending
} direction = Ascending;
std::vector<Peak>peaks;
for (int x = 0; x < m_matrixWidth - 1; x++) {
for (int y = 0; y < m_matrixHeight - 1; y++) {
double currentValue = m_matrix[x*m_matrixHeight + y];
if (prevVal < currentValue) {
direction = Ascending;
}
else if (prevVal > currentValue) {
if (direction != Descending) {
if (currentValue > NOISE) {
Peak peak(x, y, currentValue);
peaks.push_back(peak);
std::cout << "peak at index " << x*m_matrixHeight + y << ": " << prevVal << std::endl;
}
direction = Descending;
}
}
prevVal = currentValue;
}
}
return peaks;
This is how it looks:
If anyone knows, thanks.
Given a number x, insert elements 1 to x^2 in a matrix spirally.
e.g. For x = 3, matrix looks like [[1,2,3],[8,9,4],[7,6,5]].
For this I've written following snippet. However, I'm getting o/p as [[7,9,5],[7,9,5],[7,9,5]]
while(t<=b && l<=r){
System.out.print(t+" "+b+" "+l+" "+r+"\n");
if(dir==0){
for(int i = l;i<=r;i++){
arr.get(t).set(i,x);
x++;
}
t++;
}else if(dir==1){
for(int i = t;i<=b;i++){
arr.get(i).set(r,x);
x++;
}
r--;
}else if(dir==2){
for(int i = r;i>=l;i--){
arr.get(b).set(i,x);
x++;
}
b--;
}else if(dir==3){
for(int i = b;i>=t;i--){
arr.get(l).set(i,x);
x++;
}
l++;
}
dir = (dir+1)%4;
}
You can use the next code (which I developed for some implementation that handles huge martrix sizes). It will use width (columns) and height (rows) of any matrix size and produce the output you need
List<rec> BuildSpiralIndexList(long w, long h)
{
List<rec> result = new List<rec>();
long count = 0,dir = 1,phase = 0,pos = 0;
long length = 0,totallength = 0;
bool isVertical = false;
if ((w * h)<1) return null;
do
{
isVertical = (count % 2) != 0;
length = (isVertical ? h : w) - count / 2 - count % 2;
phase = (count / 4);
pos = (count % 4);
dir = pos > 1 ? -1 : 1;
for (int t = 0; t < length; t++)
// you can replace the next code with printing or any other action you need
result.Add(new rec()
{
X = ((pos == 2 || pos == 1) ? (w - 1 - phase - (pos == 2 ? 1 : 0)) : phase) + dir * (isVertical ? 0 : t),
Y = ((pos <= 1 ? phase + pos : (h - 1) - phase - pos / 3)) + dir * (isVertical ? t : 0),
Index = totallength + t
});
totallength += length;
count++;
} while (totallength < (w*h));
return result;
}
This solution walks from the top left to the top right, the top right to the bottom right, the bottom right to the bottom left and the bottom left up to the top left.
It is a tricky problem, hopefully my comments below assist in explaining.
Below is a codepen link to see it added to a table.
https://codepen.io/mitchell-boland/pen/rqdWPO
const n = 3; // Set this to a number
matrixSpiral(n);
function matrixSpiral(number){
// Will populate the outer array with n-times inner arrays
var outerArray = [];
for(var i = 0; i < number; i++){
outerArray.push([]);
}
var leftColumn = 0;
var rightColumn = number - 1;
var topRow = 0;
var bottomRow = number-1;
var counter = 1; // Used to track the number we are up to.
while(leftColumn <= rightColumn && topRow <=bottomRow){
// populate the top row
for(var i = leftColumn; i <= rightColumn; i++){
outerArray[leftColumn][i] = counter;
counter++;
}
// Top row is now populated
topRow ++;
// Populate the right column
for(var i = topRow ; i <= bottomRow; i++){
outerArray[i][rightColumn] = counter;
counter++;
}
// Right column now populated.
rightColumn--;
// Populate the bottom row
// We are going from the bottom right, to the bottom left
for(var i = rightColumn; i >= leftColumn; i--){
outerArray[bottomRow][i] = counter;
counter++;
}
// Bottom Row now populated
bottomRow--;
// Populate the left column
// We are going from bottom left, to top left
for(var i = bottomRow; i >= topRow ; i--){
outerArray[i][leftColumn] = counter;
counter++;
}
// Left column now populated.
leftColumn++;
// While loop will now repeat the above process, but a step in.
}
// Console log the results.
for(var i = 0; i < number; i++){
console.log(outerArray[i]);
}
}
I have a list of objects and I want three lines A, B and C for every object. I am trying this but is it still being messed on display:
for (int i = 0; i < MyListSize * 3; i++)
{
if (i % 3 == 0)
Console.Writeline("C"); // any display function
else if (i % 2 == 0)
Console.Writeline("B"); // any display function
else
Console.Writeline("A"); // any display function
}
Could any point out what is my mistake?
Current Output:
C A B C B A C A B C B A
Expected Output:
A B C A B C A B C A B C
You need to change the code:
for (int i = 0; i < MyListSize * 3; ++i) {
switch (i % 3) {
case 0:
Console.Writeline("A"); // any display function
break;
case 1:
Console.Writeline("B"); // any display function
break;
case 2:
Console.Writeline("C"); // any display function
break;
}
}
This should work for c# and c++:
for (int i = 0; i < YourListSize * 3; i++)
{
if (i % 3 == 0)
cout << "A"; // or Console.Writeline()
if (i % 3 == 1)
cout << "B";
if (i % 3 == 2)
cout << "C";
}
UPD. As #juharr said, your for loop starts with 0 and 0(mod 3) = 0, so your sequence starts with C. Just replace for line with:
for (int i = 1; i <= MyListSize; i++)
.. or refine you ifs
Until you tell us clearly what you want there'll be magic predictions, but not the solutions. Like this:
var s = string.Join(Environment.NewLine, "A", "B", "C");
for (int i = 0; i < MyListSize; i++)
{
Console.Writeline(s);
}
I am trying to make blobs finding algorithm with 8 connectivity for binary image(monochrome) (coordinates of bounding boxes up-left and down-right dots)which use small amount of memory (needed because the large resolution of the image) on C++.
There are such tools like OpenCV, but it has a lot of filters and is too slow if you want to detect each blob in binary image, there is also CvBlobsLib but the support is outdated(last version is before 5 years) and I couldn't set it up for Visual Studio 2013 (it must be compiled with Cmake, and it is giving errors). In wikipedia there are two types of algorithms - "one component of a time" and "two-pass" connected-component , but they both use labels, which mean you will have another 2D array of integers, but this will take a lot of memory because of the size of int(4 bytes), and we need int because of the image size and possibility of more than 65535 labels(which is short). If it is even short it will take twice less memory, which is again a lot of it. I found a "quickblob" written in C quicblobsalgol but I couldn't run it from the source(but exe is working properly), tried to analyze the code, and I got something, but the whole idea behind it stayed vague for me, so I tried also something like floodFill algorithm and something like "disjoined-set data structure" link which to hold the blobs, and this means the used memory theoretically is defined of the number of blobs(single black pixels are not recognize as blobs). Here is the C++ code:
#include <cstdlib>
#include <iostream>
#include <ctime>
#include <math.h>
#define ROWS 4000
#define COLS 4000
#define BLOBS 1000000
using namespace std;
void floodFillAlgorithm(short(&arr)[ROWS][COLS]);
int recurciveMarkBlob(short(&arr)[ROWS][COLS], int **ptr_labels, int i, int j, int group);
int main(){
short arr[ROWS][COLS];
srand((unsigned int)time(0)); // use current time as seed for random generator
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
arr[i][j] = rand() % 2;
}
}
/*for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
cout << arr[i][j] << '\t';
}
cout << '\n';
}*/
floodFillAlgorithm(arr);
cout << '\n';
cout << '\n';
/*for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
cout << arr[i][j] << '\t';
}
cout << '\n';
}*/
system("PAUSE");
return 0;}
void floodFillAlgorithm(short(&arr)[ROWS][COLS])
{
int group = 0;
int **ptr_labels;
ptr_labels = (int **)malloc(BLOBS * sizeof(int*));
if (ptr_labels == 0)
{
printf("ERROR: Out of memory\n");
}
for (int i = 0; i < BLOBS; i++)
{
ptr_labels[i] = NULL;
}
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
if (arr[i][j] == 1)
{
recurciveMarkBlob(arr, ptr_labels,i, j, ++group);
arr[i][j] = 1;
}
}
}
int count = 0;
for (int i = 0; i < BLOBS; i++)
{
if (ptr_labels[i] != NULL)
{
count++;
//cout << "Label: " << i << " ; X1: " << ptr_labels[i][0] << " ; Y1: " << ptr_labels[i][1] << " ; X2: " << ptr_labels[i][2] << " ; Y2: " << ptr_labels[i][3] << " ; X3: " << ptr_labels[i][4] << " ; Y3: " << ptr_labels[i][5] << " ; POINTS: " << ptr_labels[i][6] << endl;
}
}
cout << "Count: " << count << endl;
system("PAUSE");
for (int i = 0; i < BLOBS; i++)
{
if (ptr_labels[i] != NULL)
{
free(ptr_labels[i]);
}
}
free(ptr_labels);
}
int recurciveMarkBlob(short(&arr)[ROWS][COLS], int **ptr_labels, int i, int j, int group)
{
//cout << " i : " << i << " j: " << j << endl;
if (j != 0)
{
if ((arr[i][j] == arr[i][j - 1]) && (arr[i][j - 1] == 1))
{
if (ptr_labels[group] == NULL)
{
ptr_labels[group] = (int *)malloc(7 * sizeof(int*));
ptr_labels[group][0] = j - 1;
ptr_labels[group][1] = i;
ptr_labels[group][2] = j;
ptr_labels[group][3] = i;
ptr_labels[group][4] = j;
ptr_labels[group][5] = i;
ptr_labels[group][6] = 2; // taken points (area) for current shape
}
else
{
if (ptr_labels[group][0] > j - 1)
{
ptr_labels[group][0] = j - 1;
}
ptr_labels[group][6]++;
}
arr[i][j] = 0;
recurciveMarkBlob(arr, ptr_labels, i, j - 1, group);
arr[i][j] = 1;
}
}
if (j != COLS - 1)
{
if ((arr[i][j] == arr[i][j + 1]) && (arr[i][j + 1] == 1))
{
if (ptr_labels[group] == NULL)
{
ptr_labels[group] = (int *)malloc(7 * sizeof(int*));
ptr_labels[group][0] = j;
ptr_labels[group][1] = i;
ptr_labels[group][2] = j + 1;
ptr_labels[group][3] = i;
ptr_labels[group][4] = j;
ptr_labels[group][5] = i;
ptr_labels[group][6] = 2; // taken points (area) for current shape
}
else
{
if (ptr_labels[group][2] < j + 1)
{
ptr_labels[group][2] = j + 1;
}
ptr_labels[group][6]++;
}
arr[i][j] = 0;
recurciveMarkBlob(arr, ptr_labels, i, j + 1, group);
arr[i][j] = 1;
}
}
if (i != 0)
{
if ((arr[i][j] == arr[i - 1][j]) && (arr[i - 1][j] == 1))
{
if (ptr_labels[group] == NULL)
{
ptr_labels[group] = (int *)malloc(7 * sizeof(int*));
ptr_labels[group][0] = j;
ptr_labels[group][1] = i - 1;
ptr_labels[group][2] = j;
ptr_labels[group][3] = i;
ptr_labels[group][4] = j;
ptr_labels[group][5] = i;
ptr_labels[group][6] = 2; // taken points (area) for current shape
}
else
{
if (ptr_labels[group][1] > i - 1)
{
ptr_labels[group][1] = i - 1;
}
ptr_labels[group][6]++;
}
arr[i][j] = 0;
recurciveMarkBlob(arr, ptr_labels, i - 1, j, group);
arr[i][j] = 1;
}
}
if (i != ROWS - 1)
{
if ((arr[i][j] == arr[i + 1][j]) && (arr[i + 1][j] == 1))
{
if (ptr_labels[group] == NULL)
{
ptr_labels[group] = (int *)malloc(7 * sizeof(int*));
ptr_labels[group][0] = j;
ptr_labels[group][1] = i;
ptr_labels[group][2] = j;
ptr_labels[group][3] = i + 1;
ptr_labels[group][4] = j;
ptr_labels[group][5] = i;
ptr_labels[group][6] = 2; // taken points (area) for current shape
}
else
{
if (ptr_labels[group][3] < i + 1)
{
ptr_labels[group][3] = i + 1;
}
ptr_labels[group][6]++;
}
arr[i][j] = 0;
recurciveMarkBlob(arr, ptr_labels, i + 1, j, group);
arr[i][j] = 1;
}
}
if ((i != 0) && (j != 0))
{
if ((arr[i][j] == arr[i - 1][j - 1]) && (arr[i - 1][j - 1] == 1))
{
if (ptr_labels[group] == NULL)
{
ptr_labels[group] = (int *)malloc(7 * sizeof(int*));
ptr_labels[group][0] = j - 1;
ptr_labels[group][1] = i - 1;
ptr_labels[group][2] = j;
ptr_labels[group][3] = i;
ptr_labels[group][4] = j;
ptr_labels[group][5] = i;
ptr_labels[group][6] = 2; // taken points (area) for current shape
}
else
{
if (ptr_labels[group][0] > j - 1)
{
ptr_labels[group][0] = j - 1;
}
if (ptr_labels[group][1] > i - 1)
{
ptr_labels[group][1] = i - 1;
}
ptr_labels[group][6]++;
}
arr[i][j] = 0;
recurciveMarkBlob(arr, ptr_labels, i - 1, j - 1, group);
arr[i][j] = 1;
}
}
if ((i != 0) && (j != COLS - 1))
{
//cout << "i: " << i << " ; j: " << j << endl;
if ((arr[i][j] == arr[i - 1][j + 1]) && (arr[i - 1][j + 1] == 1))
{
//cout << "i: " << i << " ; j: " << j << endl;
if (ptr_labels[group] == NULL)
{
ptr_labels[group] = (int *)malloc(7 * sizeof(int*));
ptr_labels[group][0] = j;
ptr_labels[group][1] = i - 1;
ptr_labels[group][2] = j + 1;
ptr_labels[group][3] = i;
ptr_labels[group][4] = j;
ptr_labels[group][5] = i;
ptr_labels[group][6] = 2; // taken points (area) for current shape
//cout << "Label: " << group << " ; X1: " << ptr_labels[group][0] << " ; Y1: " << ptr_labels[group][1] << " ; X2: " << ptr_labels[group][2] << " ; Y2: " << ptr_labels[group][3] << endl;
}
else
{
if (ptr_labels[group][2] < j + 1)
{
ptr_labels[group][2] = j + 1;
}
if (ptr_labels[group][1] > i - 1)
{
ptr_labels[group][1] = i - 1;
}
ptr_labels[group][6]++;
}
arr[i][j] = 0;
recurciveMarkBlob(arr, ptr_labels, i - 1, j + 1, group);
arr[i][j] = 1;
}
}
if ((i != ROWS - 1) && (j != 0))
{
if ((arr[i][j] == arr[i + 1][j - 1]) && (arr[i + 1][j - 1] == 1))
{
if (ptr_labels[group] == NULL)
{
ptr_labels[group] = (int *)malloc(7 * sizeof(int*));
ptr_labels[group][0] = j - 1;
ptr_labels[group][1] = i;
ptr_labels[group][2] = j;
ptr_labels[group][3] = i + 1;
ptr_labels[group][4] = j;
ptr_labels[group][5] = i;
ptr_labels[group][6] = 2; // taken points (area) for current shape
}
else
{
if (ptr_labels[group][0] > j - 1)
{
ptr_labels[group][0] = j - 1;
}
if (ptr_labels[group][3] < i + 1)
{
ptr_labels[group][3] = i + 1;
}
ptr_labels[group][6]++;
}
arr[i][j] = 0;
recurciveMarkBlob(arr, ptr_labels, i + 1, j - 1, group);
arr[i][j] = 1;
}
}
if ((i != ROWS - 1) && (j != COLS - 1))
{
if ((arr[i][j] == arr[i + 1][j + 1]) && (arr[i + 1][j + 1] == 1))
{
if (ptr_labels[group] == NULL)
{
ptr_labels[group] = (int *)malloc(7 * sizeof(int*));
ptr_labels[group][0] = j;
ptr_labels[group][1] = i;
ptr_labels[group][2] = j + 1;
ptr_labels[group][3] = i + 1;
ptr_labels[group][4] = j; // x of pixel in black
ptr_labels[group][5] = i; // y of pixel in black
ptr_labels[group][6] = 2; // taken points (area) for current shape
}
else
{
if (ptr_labels[group][2] < j + 1)
{
ptr_labels[group][2] = j + 1;
}
if (ptr_labels[group][3] < i + 1)
{
ptr_labels[group][3] = i + 1;
}
ptr_labels[group][6]++;
}
arr[i][j] = 0;
recurciveMarkBlob(arr, ptr_labels, i + 1, j + 1, group);
arr[i][j] = 1;
}
}
/**/
arr[i][j] = 0;
return 0;
}
The main question is why before end of the main function so much RAM is still in use(147 MB). The tail recursion "recurciveMarkBlob()" is using parameters by value i,j, group, and dynamic allocation of memory and that is why the memory temporary jumps to 600 MB(mostly from the parameters), after freeing the dynamically allocated memory it still takes 148 MB, the image is 4 000 x 4 000 x 2 bytes = 16 000 000 bytes = 16 MB. I have read about "function taken memory" here but I still cant understand why. If someone can explain it with assembler code what is happening and is this occurrence normal. I am using Release mode release vs debug
system("PAUSE") in main()
In process of recursion
Also everyone can give idea for fast and low memory taking algorithm for blob detection of large binary images.
The elementary recursive solution requires a lot of stack space, on the order of the size of the blobs. Multiply that by the size of the stack frame, and you get horrible bytes/pixel requirements.
The scanline filling principle can reduce that requirement by orders of magnitude. Anyway, blob detection in textures ("porous" blobs) remains problematic.
You may also consider implementing this gem: "A Linear-Time Component-Labeling Algorithm Using Contour Tracing Technique, Fu Chang, Chun-Jen Chen, and Chi-Jen Lu."
This is weird. I have this following code:
int white = 0;
int black = 0;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int total = 0;
for (int x = i - 1; x <= i + 1; x++) {
for (int y = j - 1; y <= j + 1; y++) {
total += data[x*step + y];
}
}
if (total == (255 * 9)) {
white += 1;
// data[i*step + j] = 255;
}
else {
black += 1;
// data[i*step + j] = 0;
}
}
}
cout << white << endl << black << endl;
When I run this code, it will input the white and black correctly. But for some reason, when I uncomment the data, the code will be wrong. Btw, I'm just simply eroding an image, and this is what I've come up so far.
When you uncomment those statements you will then be modifying data[] "in place" and, because you are performing a neighbourhood operation, that modified data will be re-used as input data in subsequent iterations, which will of course make the results invalid. You need a separate output image to write these new values to.
your code is overflowing.
if you want to check a 3x3 neighbourhood, you need to spare a 1 pixel border at all sides.
also, you can't do it in-place, you need a second Mat for the result.
Mat m2 = m.clone();
int white = 0;
int black = 0;
for (int i = 1; i < height - 1; i++){ // border
for (int j = 1; j < width - 1; j++){ // border
int total = 0;
for (int x = i - 1; x <= i + 1; x++){
for (int y = j - 1; y <= j + 1; y++){
total += data[x*step + y];
}
}
if (total == (255 * 9)){
white += 1;
m2.data[i*step + j] = 255; // *write* to a 2nd mat
}
else{
black += 1;
m2.data[i*step + j] = 0; // *write* to a 2nd mat
}
}
}
cout << white << endl << black << endl;