Open yml file in opencv 1.0 - c++

I have a yml file and i want to open the file for reading using the existing opencv 1.0 functions. The file contains something like this:
%YAML:1.0
Image file: "00961010.jpg"
Contours count: 8
Contours:
-
Name: FO
Count: 41
Closed: 0
Points:
-
x: 740.7766113281250000
y: 853.0124511718750000
-
x: 745.1353149414062500
y: 875.5324096679687500
Can you please provide some example of how to iterate over this data? I need only the x, y points and store then in an array. I have searched but i did not found a similar example of data and please help me. Thanks in advance!

You're going to want to look at the cvFileStorage data-structures, and functions.
Here is an example from OpenCV to get you started:
#include "cxcore.h"
int main( int argc, char** argv )
{
CvFileStorage* fs = cvOpenFileStorage( "points.yml", 0, CV_STORAGE_READ );
CvStringHashNode* x_key = cvGetHashedNode( fs, "x", -1, 1 );
CvStringHashNode* y_key = cvGetHashedNode( fs, "y", -1, 1 );
CvFileNode* points = cvGetFileNodeByName( fs, 0, "points" );
if( CV_NODE_IS_SEQ(points->tag) )
{
CvSeq* seq = points->data.seq;
int i, total = seq->total;
CvSeqReader reader;
cvStartReadSeq( seq, &reader, 0 );
for( i = 0; i < total; i++ )
{
CvFileNode* pt = (CvFileNode*)reader.ptr;
int x = cvReadIntByName( fs, pt, "x", 0 /* default value */ );
int y = cvReadIntByName( fs, pt, "y", 0 /* default value */ );
CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
printf("point%d is (x = %d, y = %d)\n", i, x, y);
}
}
cvReleaseFileStorage( &fs );
return 0;
}

Related

Detecting areas of differing colors using OpenCV?

Let's say I have the following image:
I want to be able to detect each one of the white squares amongst the black background.
I would also like to be able to acquire the center & size of each one.
I'm attempting to use the opencv library in C++ in order to achieve this. I'm doing this on a Raspberry Pi, with it's standard OS. I installed the latest opencv library by running the sudo apt-get install libopencv-dev command on the terminal. I don't have any prior experience with opencv or any of its libraries.
I understand that one can load an image, in the form of it's pixel data, in a variable of type cv::Mat. I understand how to access each pixel inside the cv::Mat variable, and I understand how to get the byte value for each pixel.
What I'm looking for now is a function or functions that would allow me to detect each one of the white squares, and give me their center positions on the image and their sizes.
Is what I'm trying to achieve even possible with opencv in C++? Is there a function that does what I'm looking for?
This is a basic operation of image processing. It is described in the OpenCV documentation.
Here's a short bit of code. Please excuse the use of Python. This looks pretty much identical in C++. All the numpy arrays are just cv::Mat objects then.
im = cv.imread("ySqre.png", cv.IMREAD_GRAYSCALE)
(nlabels, labelmap, stats, centroids) = cv.connectedComponentsWithStats(im)
And the results:
# NOTE: background is counted as a label too, with label index 0
# nlabels: 6 (5 + background)
# centroids:
# array([[320.17971, 160.72618], # this is background, ignore it
# [ 84.5 , 56.5 ],
# [288.5 , 88.5 ],
# [437. , 140. ],
# [185. , 222.5 ],
# [527.5 , 237.5 ]])
# for the sizes, inspect the `stats` array.
# Use cv.CC_STAT_WIDTH and CC_STAT_HEIGHT for indices into the array.
# There is also the top left corner and the area in number of pixels.
# stats:
# array([[ 0, 0, 640, 320, 190359], # background, ignore
# [ 48, 39, 74, 36, 2664],
# [ 274, 62, 30, 54, 1620],
# [ 412, 81, 51, 119, 6069],
# [ 159, 195, 53, 56, 2968],
# [ 514, 218, 28, 40, 1120]], dtype=int32)
If you can assume the detection target area is white and its shape is (non-rotated) rectangle, simply doing labeling will achieve your detection (because of the assumption : all found white region should be rectangle).
You say you can access pixel data, so, you can implement simple labeling process for this purpose.
Very simple sample code:
#include <iostream>
#include <vector>
struct HorizontalLineSeg
{
int left, right, y;
HorizontalLineSeg( int left=0, int right=0, int y=0 )
: left(left), right(right), y(y)
{}
};
struct RectReg
{
HorizontalLineSeg Top, Bottom;
RectReg( const HorizontalLineSeg &Top ) : Top(Top),Bottom(Top) {}
bool ConnectToBottom( const HorizontalLineSeg &Seg )
{
if( Bottom.y+1 != Seg.y )return false;
if( Seg.right < Bottom.left || Bottom.right < Seg.left )return false;
Bottom = Seg;
return true;
}
};
void Update( std::vector<RectReg> &Regs, const HorizontalLineSeg &FoundSeg )
{
for( auto &Reg : Regs )
{
if( Reg.ConnectToBottom( FoundSeg ) )return;
}
Regs.emplace_back( FoundSeg);
}
int main()
{
//- Load Image as GrayScale
cv::Mat Img = cv::imread( "WhiteRects.png", cv::IMREAD_GRAYSCALE );
if( Img.empty() ){ std::cout << "imread() failed" << std::endl; return 0; }
//- Find white regions
std::vector<RectReg> Regs;
{
const unsigned char Thresh = 128;
for( int y=0; y<Img.rows; ++y )
{
const unsigned char *p = Img.ptr<unsigned char>( y );
int FoundLeft = -1;
for( int x=0; x<Img.cols; ++x, ++p )
{
if( *p >= Thresh )
{
if( FoundLeft<0 )FoundLeft = x;
}
else if( FoundLeft >= 0 )
{
Update( Regs, HorizontalLineSeg( FoundLeft, x-1, y ) );
FoundLeft = -1;
}
}
}
}
//- Visualize result
cv::Mat ShowImg = Img * 0.35;
if( !Regs.empty() )
{
std::vector< std::vector<cv::Point> > Pts;
Pts.reserve( Regs.size() );
for( const auto &Reg : Regs )
{
Pts.push_back(
{
{ Reg.Top.left, Reg.Top.y },
{ Reg.Top.right, Reg.Top.y },
{ Reg.Bottom.right, Reg.Bottom.y },
{ Reg.Bottom.left, Reg.Bottom.y }
}
);
}
cv::polylines( ShowImg, Pts, true, cv::Scalar(255) );
}
std::cout << Regs.size() << " regs found" << std::endl;
cv::imshow( "Result", ShowImg );
cv::waitKey();
return 0;
}
Added code that uses OpenCV functions because it seems to be criticized for not using OpenCV functions.
int main()
{
//- Load Image as GrayScale
cv::Mat Img = cv::imread( "WhiteRects.png", cv::IMREAD_GRAYSCALE );
if( Img.empty() ){ std::cout << "imread() failed" << std::endl; return 0; }
//- Main process with cv::connectedComponentsWithStats()
cv::Mat Stats;
int N = 0;
{
//- Pre-Binalize with OpenCV's function.
// Purpose of this is just to set the background value to 0.
// So, if you know the backgroud value is already 0, you can omit this step.
cv::Mat BinImg;
cv::threshold( Img, BinImg, 128, 255, cv::THRESH_BINARY );
//- Use connectedComponentsWithStats()
cv::Mat Labels; //Only needed to use the function.
cv::Mat Centroids; //Only needed to use the function. Or you can use this if you want.
N = cv::connectedComponentsWithStats( BinImg, Labels, Stats, Centroids );
}
//- Visualize result
cv::Mat ShowImg = Img * 0.35;
for( int i=1; i<N; ++i ) //be careful not to include 0
{
const int *pS = Stats.ptr<int>( i );
cv::rectangle(
ShowImg,
cv::Rect(
cv::Point{ pS[ cv::CC_STAT_LEFT ], pS[ cv::CC_STAT_TOP ] },
cv::Size{ pS[ cv::CC_STAT_WIDTH ], pS[ cv::CC_STAT_HEIGHT ] }
),
cv::Scalar(255)
);
}
std::cout << N-1 << " regs found" << std::endl; //not N
cv::imshow( "Result", ShowImg );
cv::waitKey();
return 0;
}

GDALWarpRegionToBuffer & Tiling when Dst Frame not strictly contained in Src Frame

I'm currently working with gdal api C/C++ and I'm facing an issue with gdal warp region to buffer functionality (WarpRegionToBuffer).
When my destination dataset is not strictly contained in the frame of my source dataset, the area where there should be no data values is filled with random data (see out_code.tif enclosed). However gdalwarp command line functionality, which also uses WarpRegionToBuffer function, does not seem to have this problem.
1/ Here is the code I use:
#include <iostream>
#include <string>
#include <vector>
#include "gdal.h"
#include "gdalwarper.h"
#include "cpl_conv.h"
int main(void)
{
std::string pathSrc = "in.dt1";
//these datas will be provided by command line
std::string pathDst = "out_code.tif";
double resolutionx = 0.000833333;
double resolutiony = 0.000833333;
//destination corner coordinates: top left (tl) bottom right (br)
float_t xtl = -1;
float_t ytl = 45;
float_t xbr = 2;
float_t ybr = 41;
//tile size defined by user
int tilesizex = 256;
int tilesizey = 256;
float width = std::ceil((xbr - xtl)/resolutionx);
float height = std::ceil((ytl - ybr)/resolutiony);
double adfDstGeoTransform[6] = {xtl, resolutionx, 0, ytl, 0, -resolutiony};
GDALDatasetH hSrcDS, hDstDS;
// Open input file
GDALAllRegister();
hSrcDS = GDALOpen(pathSrc.c_str(), GA_ReadOnly);
GDALDataType eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1));
// Create output file, using same spatial reference as input image, but new geotransform
GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
hDstDS = GDALCreate( hDriver, pathDst.c_str(), width, height, GDALGetRasterCount(hSrcDS), eDT, NULL );
OGRSpatialReference oSRS;
char *pszWKT = NULL;
//force geo projection
oSRS.SetWellKnownGeogCS( "WGS84" );
oSRS.exportToWkt( &pszWKT );
GDALSetProjection( hDstDS, pszWKT );
//Fetches the coefficients for transforming between pixel/line (P,L) raster space,
//and projection coordinates (Xp,Yp) space.
GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
// Setup warp options
GDALWarpOptions *psWarpOptions = GDALCreateWarpOptions();
psWarpOptions->hSrcDS = hSrcDS;
psWarpOptions->hDstDS = hDstDS;
psWarpOptions->nBandCount = 1;
psWarpOptions->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount );
psWarpOptions->panSrcBands[0] = 1;
psWarpOptions->panDstBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount );
psWarpOptions->panDstBands[0] = 1;
psWarpOptions->pfnProgress = GDALTermProgress;
//these datas will be calculated in order to warp tile by tile
//current tile size
int cursizex = 0;
int cursizey = 0;
double nbtilex = std::ceil(width/tilesizex);
double nbtiley = std::ceil(height/tilesizey);
int starttilex = 0;
int starttiley = 0;
// Establish reprojection transformer
psWarpOptions->pTransformerArg =
GDALCreateGenImgProjTransformer(hSrcDS,
GDALGetProjectionRef(hSrcDS),
hDstDS,
GDALGetProjectionRef(hDstDS),
FALSE, 0.0, 1);
psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
// Initialize and execute the warp operation on region
GDALWarpOperation oOperation;
oOperation.Initialize(psWarpOptions);
for (int ty = 0; ty < nbtiley; ty++) {
//handle last tile size
//if it last tile change size otherwise keep tilesize
for (int tx = 0; tx < nbtilex; tx++) {
//if it last tile change size otherwise keep tilesize
starttiley = ty * tilesizey;
starttilex = tx * tilesizex;
cursizex = std::min(starttilex + tilesizex, (int)width) - starttilex;
cursizey = std::min(starttiley + tilesizey, (int)height) - starttiley;
float * buffer = new float[cursizex*cursizey];
memset(buffer, 0, cursizex*cursizey);
//warp source
CPLErr ret = oOperation.WarpRegionToBuffer(
starttilex, starttiley, cursizex, cursizey,
buffer,
eDT);
if (ret != 0) {
CEA_SIMONE_ERROR(CPLGetLastErrorMsg());
throw std::runtime_error("warp error");
}
//write the fuzed tile in dest
ret = GDALRasterIO(GDALGetRasterBand(hDstDS,1),
GF_Write,
starttilex, starttiley, cursizex, cursizey,
buffer, cursizex, cursizey,
eDT,
0, 0);
if (ret != 0) {
CEA_SIMONE_ERROR("raster io write error");
throw std::runtime_error("raster io write error");
}
delete(buffer);
}
}
// Clean memory
GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );
GDALDestroyWarpOptions( psWarpOptions );
GDALClose( hDstDS );
GDALClose( hSrcDS );
return 0;
}
The result:
output image of previous sample of code (as png, as I can't enclose TIF img)
The GdalWarp command line:
gdalwarp -te -1 41 2 45 -tr 0.000833333 0.000833333 in.dt1 out_cmd_line.tif
The command line result:
output image of previous command line (as png, as I can't enclose TIF img)
Can you please help me find what is wrong with my use of GDAL C/C++ API in order to have a similar behaviour as gdalwarp command line? There is probably an algorithm in gdalwarp that computes a mask of useful pixels in destination frame before calling WarpRegionToBuffer, but I didn't find it.
I would really appreciate help on this problem!
Best regards

How i can set rgb color?

How i can set rgb color to anything component? FireMonkey, C++ Builder XE8.
I have used this code but its useless...
Rectangle1->Fill->Color = RGB(255, 50, 103);
Rectangle1->Fill->Color = (TColor)RGB(255, 50, 103);
May be i must use RGBA? But i dont know how to do it.
I did it.
UnicodeString s ;
s = "0xFF" ;
s += IntToHex ( 255 , 2 );
s += IntToHex ( 50 , 2 );
s += IntToHex ( 103 , 2 );
Rectangle1 -> Fill -> Color = StringToColor ( s );
This function will allow you to convert int specified RGB values to a TAlphaColor, which is what is used by FireMonkey.
TAlphaColor GetAlphaColor (int R, int G, int B)
{
TAlphaColorRec acr;
acr.R = R;
acr.G = G;
acr.B = B;
acr.A = 255;
return acr.Color;
}

GDAL GeoTiff Corrupt on Write (C++ )

I'm getting corrupt output when writing a GeoTiff using GDAL API (v1.10 - C++). The raster geotransform is correct, the block is written in the correct position but the pixels are written at random positions and values within the block.
Example: http://i.imgur.com/mntnAfK.png
Method: Open a GDAL Raster --> copy projection info & size --> create output GeoTiff --> write a block from array at offset.
Code:
//Open the input DEM
const char* demFName = "/Users/mount.dem";
const char* outFName = "/Users/geodata/out_test.tif";
auto poDataset = ioUtils::openDem(demFName);
double adfGeoTransform[6];
poDataset->GetGeoTransform( adfGeoTransform );
//Setup driver
const char *pszFormat = "GTiff";
GDALDriver *poDriver;
poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
char *pszSRS_WKT = NULL;
GDALRasterBand *poBand;
//Get size from input Raster
int xSize = poDataset->GetRasterXSize();
int ySize = poDataset->GetRasterYSize();
//Set output Dataset
GDALDataset *poDstDS;
char **papszOptions = NULL;
//Create output geotiff
poDstDS = poDriver->Create( outFName, xSize, ySize, 1, GDT_Byte, papszOptions );
//Get the geotrans from the input geotrans
poDataset->GetGeoTransform( adfGeoTransform );
poDstDS->SetGeoTransform( adfGeoTransform );
poDstDS->SetProjection( poDataset->GetProjectionRef() );
//Create some data to write
unsigned char rData[512*512];
//Assign some values other than 0
for (int col=0; col < 512; col++){
for (int row=0; row < 512; row++){
rData[col*row] = 50;
}
}
//Write some data
poBand = poDstDS->GetRasterBand(1);
poBand->RasterIO( GF_Write, 200, 200, 512, 512,
rData, 512, 512, GDT_Byte, 0, 0 );
//Close
GDALClose( (GDALDatasetH) poDstDS );
std::cout << "Done" << std::endl;
Any ideas / pointers where I'm going wrong much appreciated.
Always something trivial...
rData[row*512+col] = 50
Qudos to Even Rouault on osgeo.

How to update wxTreeListCtrl in real time if the childrens count is more 100000 in wxwidgets

I am going to display data in wxTreeListCtrl but i am facing some problems with time ,
it is taking much time , could some please hep me out of this.
Here is my code:
wxTreeListCtrl *m_ptreelistctrl = new wxTreeListCtrl(this, TREELISTCNTRL, pos, size, wxBORDER_NONE|wxTR_HAS_BUTTONS|wxTR_MULTIPLE, validator, name);
m_ptreelistctrl->SetHeaderBackgroundcolour(colour);
//For Displaying Names
m_ptreelistctrl->AddColumn(_U("Description") , 400 ,wxALIGN_LEFT /*,DEFAULT_ITEM_WIDTH, wxALIGN_LEFT */);
//For Displaying ID
m_ptreelistctrl->AddColumn(_U("Id"), 50/*30*/, wxALIGN_LEFT ,-1 ,false);
//For Displaying Colour
m_ptreelistctrl->AddColumn(_U("Colour"), DEFAULT_COL_WIDTH, wxALIGN_LEFT/*CENTER */);
wxStopWatch *time = new wxStopWatch();
time->Start();
custTreeItemData* pcusData = new custTreeItemData(-1, TREEITEM_ROOT);
root = m_ptreelistctrl->AddRoot(m_strRootname, -1,-1,pcusData);
pcusData = new custTreeItemData(-1, TREEITEM_ASSMB);
item_assmb = m_ptreelistctrl->AppendItem( root,"Assem", 0, 3, pcusTrData);
for ( i = 1; i <= 100000; i++ )
{
unsigned char r,g,b;
wxTreeItemId item_assmb_entities;
custTreeItemData* pcusTrData = new custTreeItemData(i, TREEITEM_ASSMB);
pcusTrData->SetDataId(10);
item_assmb_entities = m_ptreelistctrl->AppendItem(item_assmb,"srinvas", 0, 3, pcusTrData);
FillItems(pcusTrData,item_assmb_entities);
AppendColorImagetoTree( item_assmb_entities, 2, r, g, b );
AppendIdtoTree(item_assmb_entities ,1 ,10);
if( true )
{
m_ptreelistctrl->SetItemImage( item_assmb_entities, 0, 3 , wxTreeItemIcon_Selected);
m_ptreelistctrl->SetItemImage( item_assmb_entities, 0, 3 );
pcusTrData->SetCheckStatus(true);
}
else
{
m_ptreelistctrl->SetItemImage( item_assmb_entities, 0, 2 , wxTreeItemIcon_Selected);
m_ptreelistctrl->SetItemImage( item_assmb_entities, 0, 2 );
pcusTrData->SetCheckStatus(false);
}
}
pcusData = new custTreeItemData(-1, TREEITEM_COMPS);
item_comp = m_ptreelistctrl->AppendItem( root,"Comps", 0, 3, pcusTrData);
for ( i = 1; i <= 100000; i++ )
{
unsigned char r,g,b;
wxTreeItemId item_comp_entities;
custTreeItemData* pcusTrData = new custTreeItemData(i, TREEITEM_COMPS);
pcusTrData->SetDataId(10);
item_comp_entities= m_ptreelistctrl->AppendItem( item_comp,"Comps", 0, 3, pcusTrData);
FillItems(pcusTrData,item_comp_entities);
AppendColorImagetoTree( item_comp_entities, 2, r, g, b );
AppendIdtoTree(item_comp_entities,1 ,10);
if( true )
{
m_ptreelistctrl->SetItemImage( item_comp_entities, 0, 3 , wxTreeItemIcon_Selected);
m_ptreelistctrl->SetItemImage( item_comp_entities, 0, 3 );
pcusTrData->SetCheckStatus(true);
}
else
{
m_ptreelistctrl->SetItemImage( item_comp_entities, 0, 2 , wxTreeItemIcon_Selected);
m_ptreelistctrl->SetItemImage( item_comp_entities, 0, 2 );
pcusTrData->SetCheckStatus(false);
}
}
time->Pause();
int cc = time->Time();
wxString strda;
strda.Printf("time taken%d" ,cc);
wxMessageBox(strda.c_str());
Issue: I am going to display more then 200000 childrens but taking time around 17 Minutes
to construct tree ,
My answer assumes that you have made sure that the bottleneck is indeed the wxTreeListCtrl. It might as well be in your own code, so make sure of this before proceeding!
That being said, I think in this case you are better off using wxDataViewCtrl with a custom wxDataViewModel. The difference is that wxTreeListCtrl stores the entire tree in memory and offers no way to batch update the model / view, which might lead to the performance problems. In contrast, wxDataViewCtrl is just a view of your own model, which you have to adapt using your own implementation of wxDataViewModel. Note that wxDataViewModel has functions for batch updating the view, e.g. ItemsAdded, ItemsDeleted, ItemsChanged.
Hope this helps!