Related
Im having an issue using opencv trying to convert an image to an array. The conversion works however i seem to have incorrect dimensions in the resulting array:
#include <opencv2/opencv.hpp>
int main()
{
auto img = cv::imread("test.jpg", CV_LOAD_IMAGE_COLOR);
std::cout << "img cols: " << img.cols << " img rows: "
<< img.rows << " channels: " << img.channels() << std::endl;
std::vector<float> array2;
if (img.isContinuous()) {
array2.assign((float*)img.ptr(0), (float*)(img.ptr(img.rows - 1)) + img.cols);
std::cout << array2.size() << "\n";
}
return 0;
}
The output from the first print line results in :
img cols: 416 img rows: 416 channels: 3
Which is correct, however after assigning the data to the array the dimensions are : 518336 , when they should be 519168 (416*416*3).
Could anyone possibly suggest what exactly is causing the resulting array to be smaller than expected?
There are several problems with your code:
First of all, cv::imread("test.jpg", CV_LOAD_IMAGE_COLOR); will (on success) return a cv::Mat with datatype CV_8UC3, however you're accessing the elements as floats. This means that the values you will read will be garbage, and you will also end up reading past the end of the pixel buffer.
If you want floats, then you need to do some conversion/casting, either before or during the act of copying.
The second problem lies in your calculation of the "end" pointer, where you seem to forget that you're dealing with a multi-channel cv::Mat. In case of a CV_8UC3 matrix, each pixel is represented by 3 bytes, hence there are cols*channels bytes per row. (That's why you're short by 2*416 elements)
Not really a problem, but a limitation -- your code only works for continuous Mats.
I would take a somewhat different approach, and take advantage of functionality provided by OpenCV.
Option 1
Use cv::Mat::copyTo, since OutputArray can wrap a std::vector<T>. However, for this to work, the source Mat needs to have 1 channel and 1 row. We can achieve this efficiently using cv::Mat::reshape, but the Mat needs to be continuous, so that limitation stays.
std::vector<uchar> to_array_v1(cv::Mat3b const& img)
{
std::vector<uchar> a;
if (img.isContinuous()) {
img.reshape(1, 1).copyTo(a);
}
return a;
}
Option 2
Use MatIterators which we can get using cv::Mat::begin and cv::Mat::end. The iterators will work correctly even on a non-continuous Mat, however we need them to iterate over bytes, so we need to reshape the matrix to a single channel one. Since we're not changing the number of rows, the reshape will also work on a non-continuous Mat.
std::vector<uchar> to_array_v2(cv::Mat3b const& img)
{
cv::Mat1b tmp(img.reshape(1));
return std::vector<uchar>(tmp.begin(), tmp.end());
}
Option 3
The approach suggested by Silencer, using the rather poorly documented cv::Mat::datastart and cv::Mat::dataend members. The documentation of cv::Mat::locateROI sheds some more light on the meaning of those member variables:
However, each submatrix contains information (represented by datastart and dataend fields) that helps reconstruct the original matrix size and the position of the extracted submatrix within the original matrix.
This means that this approach has 2 limitations: it needs a continous matrix, and it won't work correctly for a submatrix, even if it's continuous. (Specifically, for a continuous submatrix, it would return the entire buffer of the "parent" matrix)
std::vector<uchar> to_array_v3(cv::Mat3b const& img)
{
std::vector<uchar> a;
if (img.isContinuous() && !img.isSubmatrix()) {
a.assign(img.datastart, img.dataend);
}
return a;
}
Test Code
#include <opencv2/opencv.hpp>
#include <iostream>
#include <numeric>
#include <vector>
// Paste implementations from the answer here
cv::Mat3b test_image()
{
cv::Mat1b m(4, 4);
std::iota(m.begin(), m.end(), 0);
cv::Mat3b img;
cv::merge(std::vector<cv::Mat1b>{ m * 3, m * 3 + 1, m * 3 + 2 }, img);
return img;
}
void print(cv::Mat3b const& img)
{
std::cout << "Continuous: " << (img.isContinuous() ? "yes" : "no") << '\n';
std::cout << "Submatrix: " << (img.isSubmatrix() ? "yes" : "no") << '\n';
std::cout << img << "\n";
}
void print(std::vector<uchar> const& a)
{
if (a.empty()) {
std::cout << "empty";
} else {
for (auto n : a) {
std::cout << int(n) << ' ';
}
}
std::cout << "\n";
}
void test(cv::Mat3b const& img)
{
print(img);
print(to_array_v1(img));
print(to_array_v2(img));
print(to_array_v3(img));
}
int main()
{
cv::Mat3b img(test_image());
test(img);
cv::Mat3b img2(img(cv::Rect(0, 0, 3, 3)));
test(img2);
cv::Mat3b img3(img(cv::Rect(1, 1, 3, 1)));
test(img3);
return 0;
}
Running this program will produce the following output:
Continuous: yes
Submatrix: no
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11;
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23;
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35;
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
Continuous: no
Submatrix: yes
[ 0, 1, 2, 3, 4, 5, 6, 7, 8;
12, 13, 14, 15, 16, 17, 18, 19, 20;
24, 25, 26, 27, 28, 29, 30, 31, 32]
empty
0 1 2 3 4 5 6 7 8 12 13 14 15 16 17 18 19 20 24 25 26 27 28 29 30 31 32
empty
Continuous: yes
Submatrix: yes
[ 15, 16, 17, 18, 19, 20, 21, 22, 23]
15 16 17 18 19 20 21 22 23
15 16 17 18 19 20 21 22 23
empty
Mat img = imread("test.png");
std::vector<uchar> arr;
// convert Mat of CV_8UC3 to std::vector<uchar> if continuous
if(img.isContinuous()){
arr.assign(img.datastart, img.dataend);
}
What would be the most efficient (i.e. balance memory and speed) way to access the upper or lower triangular elements of an Armadillo matrix? I know I could provide a vector of integers for the elements but as matrices become very large I would like avoid carrying around another large vector. Or is there an efficient way to quickly create the lower/upper triangular indices?
For example with a 5x5 matrix
// C++11 Initialization
arma::mat B = { 1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20,
21, 22, 23, 24, 25 };
B.reshape(5,5);
// the matrix
//1 6 11 16 21
//2 7 12 17 22
//3 8 13 18 23
//4 9 14 19 24
//5 10 15 20 25
I would like to pull the elements in the lower triangle where the result vector would be:
2 3 4 5 8 9 10 14 15 20
The only solution I can think of right now is using a uvec object. For example:
arma::uvec idx {1,2,3,4,7,8,9,13,14,19);
arma::vec lower_elems = B.elem(idx);
The final object doesn't need to be a vector. I just need to be able to access the elements for various comparisons. As a simple example let's say I would want to check if they all equal 0.
To check if all the elements in the lower triangle are equal to zero:
bool all_zero = all( X.elem(find(trimatl(X))) == 0 );
Armadillo 9.900 has the functions trimatu_ind() and trimatl_ind(). These functions provide the indices of the upper and lower triangular portions of a matrix. These indices can be used with .elem() to access the elements in upper/lower triangular portions.
There are also the functions .is_trimatu() and .is_trimatl() which check if a matrix is upper/lower trinagular.
I have the following text file strucutre:
<Game Draw> <Ticket ID> <Ticket Numbers>*6
<Game Draw> <Ticket ID> <Ticket Numbers>*6
Example:
123 ABACD T1245 5 8 10 13 25 63
123 ABACD T1245 6 7 9 12 61 63
252 FYHGO T9736 8 9 10 11 12 13
252 GTGOH T5436 10 11 12 13 14 15
Each Line is for a A lottery Ticket. - A Ticket can have multiple Lines - and a Draw can have multiple tickets.
I am wanting to do a filter on all of the results for a particular draw. Obviously, All of the players are not going to be in every draw - and a draw can have multiple tickets in (with multiple ticket Lines). IS it therefore possible to group all of the tickets into multiple layers (A Map - within a Map?) so that I can easily process this information. Or Am I best off just processing this all line by line and putting it into a structure of some description.
Many thanks,
I think you may need to use regular expression and a user-define structure for processing as well.
This code is just a little code snippet.
//Originally, each data is from txt file.
//but, this is just sample.
struct Ticket_Info
{
int first_number;
string game_draw;
string ticket_id;
int ticket_numbers[MAX_TICKET_NUMBER];
} tickets[] =
{
{123, "ABACD", "T1245", {5, 8, 10, 13, 25, 63}}
, {123, "ABACD", "T1245", {6, 7, 9, 12, 61, 63}}
, {252, "FYHGO", "T9736", {8, 9, 10, 11, 12, 13}}
, {252, "GTGOH", "T5436", {10, 11, 12, 13, 14, 15}}
};
std::regex match_draw_key("FYHGO");
for_each(std::begin(tickets), std::end(tickets), [&](const Ticket_Info &ticket)
{
std::cout << ticket.ticket_id << ": " << std::regex_match(ticket.game_draw, match_draw_key) << '\n';
});
I hope this will help you a little.
I'm trying to encode a relatively complex message into a union structure so that I can generate an array of uint8_t that I can feed into a serial communications protocol.
However, when looking at the array generated when my union is filled with data, an extra uint8_t element appears after my command type element. Please see the Union structure below:
union myint16_t{
uint16_t ui16;
int16_t i16;
uint8_t data[2];
};
union {
struct {
uint8_t commandtype;
myint16_t UpperLimits[4];
myint16_t LowerLimits[4];
myint16_t JointZeros[4];
int8_t JointPolarity[4];
myint16_t P[4];
myint16_t I[4];
myint16_t D[4];
};
uint8_t data[53];
};
as you can see there are the second anonymous union references the union myint16_t.
So if I fill all the values of the anonymous union and then print out the underlying data[53] array, my second value (data[1]) is 0 and not part of the first element of UpperLimits[4]. Please see the code where I fill the union and then print out the elements.
char q = 'c';
hmmv4_configmsg msg;
msg.commandtype =(uint8_t) q;
msg.UpperLimits[0].ui16 = 784;
msg.UpperLimits[1].ui16 = 784;
msg.UpperLimits[2].ui16 = 784;
msg.UpperLimits[3].ui16 = 784;
msg.LowerLimits[0].ui16 = 223;
msg.LowerLimits[1].ui16 = 223;
msg.LowerLimits[2].ui16 = 223;
msg.LowerLimits[3].ui16 = 223;
msg.JointZeros[0].ui16 = 512;
msg.JointZeros[1].ui16 = 512;
msg.JointZeros[2].ui16 = 512;
msg.JointZeros[3].ui16 = 512;
msg.JointPolarity[0] = -1;
msg.JointPolarity[1] =-1;
msg.JointPolarity[2] =-1;
msg.JointPolarity[3] =-1;
msg.P[0].i16=4000;
msg.P[1].i16=4000;
msg.P[2].i16=4000;
msg.P[3].i16=4000;
msg.I[0].i16=1;
msg.I[1].i16=1;
msg.I[2].i16=1;
msg.I[3].i16=1;
msg.D[0].i16=24;
msg.D[1].i16=24;
msg.D[2].i16=24;
msg.D[3].i16=24;
//msg.change_endian();
while(1)
{
for(int i =0; i<54; i++)
{
writebuf[i]=msg.data[i];
printf("D: %d, %d \n", i, msg.data[i]);
}
printf("L0: %d, %d, %d", msg.P[0].i16, msg.P[0].data[0], msg.P[0].data[1]);
int r =jointencoder.xfer1(writebuf, readbuf, 54);
}
the output of the printf is (the offending element is D:1 -- it shouldn't be there):
D: 0, 99
D: 1, 0
D: 2, 16
D: 3, 3
D: 4, 16
D: 5, 3
D: 6, 16
D: 7, 3
D: 8, 16
D: 9, 3
D: 10, 223
D: 11, 0
D: 12, 223
D: 13, 0
D: 14, 223
D: 15, 0
D: 16, 223
D: 17, 0
D: 18, 0
D: 19, 2
D: 20, 0
D: 21, 2
D: 22, 0
D: 23, 2
D: 24, 0
D: 25, 2
D: 26, 255
D: 27, 255
D: 28, 255
D: 29, 255
D: 30, 160
D: 31, 15
D: 32, 160
D: 33, 15
D: 34, 160
D: 35, 15
D: 36, 160
D: 37, 15
D: 38, 1
D: 39, 0
D: 40, 1
D: 41, 0
D: 42, 1
D: 43, 0
D: 44, 1
D: 45, 0
D: 46, 24
D: 47, 0
D: 48, 24
D: 49, 0
D: 50, 24
D: 51, 0
D: 52, 24
D: 53, 0
L0: 4000, 160, 15joint encoder transferred
My question is why is D:1 there? My understanding of unions and structures is that because command type is uint8_t, then it should only occupy one data space, and therefore UpperLimits[0] should start on D:1, but it seems that command_type is acting as a uint16_t and posting another bit. Why is this so?
Note: you may see that the index goes up to count data[53] which should be out of bounds, but I need to read this and send it so as to be able to deconstruct the data at the other end.
There is almost certainly a padding byte between commandtype and UpperLimits; the 2-byte myint16_t data type is aligned on an even byte boundary.
struct {
uint8_t commandtype;
myint16_t UpperLimits[4];
...
If you could print the size of the anonymous structure and union, you're likely to find that it is at least 54 bytes (where you think it should be 53). One of the disadvantages of untagged structure types embedded as anonymous members of a union is that there is no easy way to print the size of the structure. Give the structure a tag (struct tag { uint8_t commandtype; ...) so that you can print its size out.
There isn't an easy fix for that using the current framework.
You need to tell the compiler how to align the elements in your union or struct. Simply add #pragma pack(push,1) before your definitions to instruct the compiler to align adjacent elements on one-byte boundaries, and then use #pragma pack(pop) to revert to the compiler's default alignment. For performance reasons, you would not want to use one-byte alignment for all structs/unions/classes, so it's a good idea to wrap your union definition in the pragma pair.
Example:
#pragma pack(push,1)
union
{
uint_8 first;
uint_8 second;
} two_bytes;
#pragma pack(pop)
assert(sizeof two_bytes == 2);
I am trying to find a way to import stat data into a game in progress Via spread sheets? Here's what I am working with:
Right now for example.. The spells, in order to name them, set stats, ect and be able to call them via Number I Have something like this going on in the actual code:
void spell(int & eMoney, int eSpell[10])
{
using namespace std;
char spellname[10][25] = {"Minor Heal", "Fire Shard", "Lightening Shard", "Ice Shard", "Magic Barrier", "Essence Of Life",
"Earth Shard", "Wind Shard", "Insigma", "Weaken"};
int spellcost[10] = {50, 80, 80, 80, 100, 100, 80, 80, 120, 80};
Which is all fine and dandy, it works... But it's an issue now and later.. I want to be able to use a spread sheet, like a CSV file, so I can have a spread sheet for like just spells, just swords, just clubs... I plan to have a very large selection, it's more ideal to be able to edit a single file in columns and rows and have the actual game pull the information from an external file when it's needed... But I am not able to figure out how to go about this? I am open to any ideas..
Here is an example of how I call on a spell's info now:
case 2:
do
{
cout << "Which spell would you like to cast?\n\n";
for(x=0;x<10;x++)
cout << x+1 << ". " << spellname[x] << ": " << eSpell[x] << " left" << endl;
cout << "11. Leave\n\n>> ";
cin >> decision;
system("cls");
}
while((decision<1)&&(decision>11)||(eSpell[decision-1]==0));
switch(decision)
and here is an example of the spread sheet I have in mind basically? Starting at A1:
Type sName mDmg sPrice
Spell 1 Minor Heal 10 100
Spell 2 Fire Shard 12 100
Spell 3 Lightening Shard 12 200
Spell 4 Ice Shard 12 150
Spell 5 Magic Barrier 10 130
Spell 6 Essence Of Life 15 10
Spell 7 Earth Shard 12 120
Spell 8 Wind Shard 12 230
Spell 9 Insigma 12 90
Spell 10 Weaken 12 100
Another Example:
Current Code:
char monsters[16][25] = {"Wolf", "Bear", "Bandit", "Traveler", "Gargoyle", "Knight", "Warlock", "Mammoth", "Cyclops", "Unicorn", "Dragon", "Your Mother", "Demon", "Jesus", "Satan", "God"};
//monster strengths
int monsterdamagemax[16] = {32, 42, 53, 53, 65, 65, 75, 75, 85, 85, 90, 90, 95, 95, 110, 110};
int monsterdamagemin[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int monsterdefensemax[16] = {2, 7, 13, 13, 20, 20, 25, 25, 35, 35, 40, 40, 45, 45, 55, 55};
int monsterdefensemin[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int monsterhealth[16] = {32, 52, 73, 73, 95, 95, 118, 118, 142, 142, 167, 167, 193, 193, 220, 220};
int monsterspeed[16] = {7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15};
int monstergold[16] = {20, 30, 41, 41, 53, 53, 66, 66, 80, 80, 95, 95, 110, 110, 125, 125};
Ideally, I want to be able to get all that from a CSV file like:
mID mName mDmgMax mDmgMin mDefMax mDefMin mHp mSpeed mGold
1 Wolf 32 0 2 0 32 7 20
2 Bear 42 0 7 0 52 8 30
3 Bandit 53 0 13 0 73 9 41
4 Traveler 53 0 13 0 73 9 41
5 Gargoyle 65 0 20 0 95 10 53
6 Knight 65 0 20 0 95 10 53
7 Warlock 75 0 25 0 118 11 66
8 Mammoth 75 0 25 0 118 11 66
9 Cyclops 85 0 35 0 142 12 80
10 Unicorn 85 0 35 0 142 12 80
11 Dragon 90 0 40 0 167 13 95
12 Your Mother 90 0 40 0 167 13 95
13 Demon 95 0 45 0 193 14 110
14 Jesus 95 0 45 0 193 14 110
15 Statan 110 0 55 0 220 15 125
16 God 110 0 55 0 220 15 125
How about writing a small command based application that creates records for you, and in your "main" program that is game, you just have to read these records.
A sample structure -
struct monster
{
int mID;
char mName[25]; //from your code
int mDmgMax;
//and these as well mDmgMin mDefMax mDefMin mHp mSpeed mGold
};
in this "helper" program read each data item (like the mName) in a record one by one, and insert in this structure. Write the structure to monsters.dat file
std::ofstream fout;
fout.open("monsters.dat", std::ios::app | std::ios::binary);
fout.write( (char*) &monsterInstance, sizeof(monsterInstance) );
fout.close();
This will simply append records. (I have skipped error checking and reading data.)
For greater ease, this program should be able to show current monsters, add monster, delete monster (by entering mID).
Reading such records in your main program should be a easy task.
If you're going to have a lot of table-based data to keep around, you might look into using SQLite. It has some interesting costs and benefits.
On the down side (maybe), it's SQL. It can be a bit more complex and depending on your searching algorithm, could be slower. It also can't be edited by hand, you need something to open the database (there are free tools available).
On the up side, you get all the sorting and filtering power of a database (anything you'll need, like spell='fireball' AND damage < 5), and SQLite is fast (easily enough to store game data in, and very possibly faster than your own code). You can store all your data in a single file for easy deployment or modding, with unique tables for each type (weapons, spells, characters, etc), and no server involved (SQLite is a single DLL).
Relational databases excel at working with consistently-formed tables of data, which is exactly what you have in a game environment (each object type has a few fields, not much variation, maybe some blanks, with various data types). SQLite, despite being the smallest database, can handle thousands of rows with excellent time, so you won't have to worry about your game data becoming unwieldy (which happens very quickly with pure text table files, like NWN(2)'s 2DA format).
There is a learning curve to it, but you do gain some simplicity in the future (adding a new object type is a new table and queries, not a whole lot of code) and a very stable data format and load/save library. Depending on your needs, it may be worth a shot.
As pointed in question comments, you should go for <fstream> if you really want to deal with CSV files. Using that approach, getline should be enough for what you need.
This thread in C++.com and this question should point you some directions on how to handle CSV.
I use Boost to parse the CSV files I work with. Here's a simple example.
I agree with peachykeen though, SQLite may suit you better, but maybe this will help you get started.
#include <iostream>
#include <fstream>
#include <vector>
#include <boost/tokenizer.hpp>
#include <boost/token_functions.hpp>
typedef std::vector<std::string> csvLine;
typedef std::vector<csvLine> csvLines;
typedef boost::tokenizer<boost::escaped_list_separator<char> > csvTokenizer;
csvLines ReadCSVFile(const std::string& fileName)
{
csvLines retVec;
std::ifstream inFile(fileName.c_str());
if(inFile)
{
std::string fileLine;
while(std::getline(inFile, fileLine))
{
csvTokenizer lineTokens(fileLine);
retVec.push_back(csvLine(lineTokens.begin(), lineTokens.end()));
}
inFile.close();
}
return retVec;
}
int main(int argc, char** argv)
{
csvLines lines(ReadCSVFile(argv[1]));
for(csvLines::iterator lineIt = lines.begin(); lineIt != lines.end(); ++lineIt)
{
for(csvLine::iterator tokenIt = (*lineIt).begin(); tokenIt != (*lineIt).end(); ++tokenIt)
{
std::cout << *tokenIt << " ";
}
std::cout << std::endl;
}
return 0;
}