Removing and re-adding elements to a vector - c++

Hi i'm somewhat new with c++ and openframeworks and I'm trying to get my program running more smooth by erasing the element from the vector when it goes out of the screen. At the moment as the time goes on it still gets slower and slower. I'm breaking my head over this. If you have any idea how I could improve this.
bool isDead(Particle &p) {
if (p.position.x > ofGetWindowWidth() || p.position.x == -1 || p.position.y > ofGetWindowHeight() || p.position.y == -1) {
return true;
}
else {
return false;
}
}
//--------------------------------------------------------------
void ofApp::setup() {
ofSetFrameRate(60);
ofEnableAlphaBlending();
ofBackground(ofColor::black);
for (int i = 0; i < 50; i++) {
Particle p;
p.setup(ofVec2f(ofRandom(ofGetWindowWidth() * 0.45, ofGetWindowWidth() * 0.55), ofRandom(ofGetWindowHeight() * 0.45, ofGetWindowHeight() * 0.55)));
particles.push_back(p);
}
beat1.load("beat1.wav");
beat2.load("beat2.wav");
beat3.load("beat3.wav");
fftSmooth = new float[8192];
for (int i = 0; i < 8192; i++) {
fftSmooth[i] = 0;
}
bands = 128;
beat1.setVolume(0.2);
beat2.setVolume(0.2);
beat3.setVolume(0.2);
}
//--------------------------------------------------------------
void ofApp::update() {
ofSoundUpdate();
float * value = ofSoundGetSpectrum(bands);
for (int i = 0; i < bands; i++) {
fftSmooth[i] *= 0.2f;
if (fftSmooth[i] < value[i]) {
fftSmooth[i] = value[i];
}
}
ofRemove(particles, isDead);
for (Particle& p : particles) {
if (!p.isActive) {
p.position = ofVec2f(ofRandom(ofGetWindowWidth() * 0.45, ofGetWindowWidth() * 0.55), ofRandom(ofGetWindowHeight() * 0.45, ofGetWindowHeight() * 0.55));
p.isActive = true;
return;
}
p.update();
}
if (isDead) {
Particle p;
p.setup(ofVec2f(0, 0));
particles.push_back(p);
}
}
//--------------------------------------------------------------
void ofApp::draw() {
for (Particle& p1 : particles) {
if (!p1.isActive) continue;
bool foundConnection = false;
//search for connections.
for (Particle& p2 : particles) {
if (!p2.isActive || p2.drawPosition == p1.drawPosition) continue;
float distance = p1.drawPosition.distance(p2.drawPosition);
for (int i = 0; i < bands; i++) {
if (distance > 10 && distance < 50 * fftSmooth[i]) {
ofDrawLine(p1.drawPosition, p2.drawPosition);
foundConnection = true;
}
}
}
for (int i = 0; i < 50; i++) {
p1.draw(-(fftSmooth[i] * 10));
}
}
}

Related

Group Consecutive Neighbouring Black Pixels Together with OpenCV [duplicate]

I am looking for an OpenCV function that can find connected components and perform a few tasks on them ( like getting the number of pixels, contour, list of pixels in the object etc.. )
Is there a function of OpenCV (C++) that is similar to MatLab's regionprops ?
Starting from version 3.0, OpenCV has connectedComponents function.
Have a look at the cvFindContours function. It's very versatile -- it can find both interior and exterior contours, and return the results in a variety of formats (e.g. flat list vs. tree structure). Once you have the contours, functions like cvContourArea allow you to determine basic properties of the connected component corresponding to a particular contour.
If you prefer to use the newer C++ interface (as opposed to the older C-style interface I described above), then the function names are similar.
set -std=c++0x option when compiling
.h file
//connected_components.h
#ifndef CONNECTED_COMPONENTS_H_
#define CONNECTED_COMPONENTS_H_
#include <opencv2/core/core.hpp>
#include <memory>
class DisjointSet {
private:
std::vector<int> m_disjoint_array;
int m_subset_num;
public:
DisjointSet();
DisjointSet(int size);
~DisjointSet();
int add(); //add a new element, which is a subset by itself;
int find(int x); //return the root of x
void unite(int x, int y);
int getSubsetNum(void);
};
class ConnectedComponent {
private:
cv::Rect m_bb;
int m_pixel_count;
std::shared_ptr< std::vector<cv::Point2i> > m_pixels;
public:
ConnectedComponent();
ConnectedComponent(int x, int y);
~ConnectedComponent();
void addPixel(int x, int y);
int getBoundingBoxArea(void) const;
cv::Rect getBoundingBox(void) const;
int getPixelCount(void) const;
std::shared_ptr< const std::vector<cv::Point2i> > getPixels(void) const;
};
void findCC(const cv::Mat& src, std::vector<ConnectedComponent>& cc);
#endif //CONNECTED_COMPONENTS_H_
.cc file
//connected_components.cpp
#include "connected_components.h"
using namespace std;
/** DisjointSet **/
DisjointSet::DisjointSet() :
m_disjoint_array(),
m_subset_num(0)
{ }
DisjointSet::DisjointSet(int size) :
m_disjoint_array(),
m_subset_num(0)
{
m_disjoint_array.reserve(size);
}
DisjointSet::~DisjointSet()
{ }
//add a new element, which is a subset by itself;
int DisjointSet::add()
{
int cur_size = m_disjoint_array.size();
m_disjoint_array.push_back(cur_size);
m_subset_num ++;
return cur_size;
}
//return the root of x
int DisjointSet::find(int x)
{
if (m_disjoint_array[x] < 0 || m_disjoint_array[x] == x)
return x;
else {
m_disjoint_array[x] = this->find(m_disjoint_array[x]);
return m_disjoint_array[x];
}
}
// point the x and y to smaller root of the two
void DisjointSet::unite(int x, int y)
{
if (x==y) {
return;
}
int xRoot = find(x);
int yRoot = find(y);
if (xRoot == yRoot)
return;
else if (xRoot < yRoot) {
m_disjoint_array[yRoot] = xRoot;
}
else {
m_disjoint_array[xRoot] = yRoot;
}
m_subset_num--;
}
int DisjointSet::getSubsetNum()
{
return m_subset_num;
}
/** ConnectedComponent **/
ConnectedComponent::ConnectedComponent() :
m_bb(0,0,0,0),
m_pixel_count(0),
m_pixels()
{
m_pixels = std::make_shared< std::vector<cv::Point2i> > ();
}
ConnectedComponent::ConnectedComponent(int x, int y) :
m_bb(x,y,1,1),
m_pixel_count(1),
m_pixels()
{
m_pixels = std::make_shared< std::vector<cv::Point2i> > ();
}
ConnectedComponent::~ConnectedComponent(void)
{ }
void ConnectedComponent::addPixel(int x, int y) {
m_pixel_count++;
// new bounding box;
if (m_pixel_count == 0) {
m_bb = cv::Rect(x,y,1,1);
}
// extend bounding box if necessary
else {
if (x < m_bb.x ) {
m_bb.width+=(m_bb.x-x);
m_bb.x = x;
}
else if ( x > (m_bb.x+m_bb.width) ) {
m_bb.width=(x-m_bb.x);
}
if (y < m_bb.y ) {
m_bb.height+=(m_bb.y-y);
m_bb.y = y;
}
else if ( y > (m_bb.y+m_bb.height) ) {
m_bb.height=(y-m_bb.y);
}
}
m_pixels->push_back(cv::Point(x,y));
}
int ConnectedComponent::getBoundingBoxArea(void) const {
return (m_bb.width*m_bb.height);
}
cv::Rect ConnectedComponent::getBoundingBox(void) const {
return m_bb;
}
std::shared_ptr< const std::vector<cv::Point2i> > ConnectedComponent::getPixels(void) const {
return m_pixels;
}
int ConnectedComponent::getPixelCount(void) const {
return m_pixel_count;
}
/** find connected components **/
void findCC(const cv::Mat& src, std::vector<ConnectedComponent>& cc) {
if (src.empty()) return;
CV_Assert(src.type() == CV_8U);
cc.clear();
int total_pix = src.total();
int frame_label[total_pix];
DisjointSet labels(total_pix);
int root_map[total_pix];
int x, y;
const uchar* cur_p;
const uchar* prev_p = src.ptr<uchar>(0);
int left_val, up_val;
int cur_idx, left_idx, up_idx;
cur_idx = 0;
//first logic loop
for (y = 0; y < src.rows; y++ ) {
cur_p = src.ptr<uchar>(y);
for (x = 0; x < src.cols; x++, cur_idx++) {
left_idx = cur_idx - 1;
up_idx = cur_idx - src.size().width;
if ( x == 0)
left_val = 0;
else
left_val = cur_p[x-1];
if (y == 0)
up_val = 0;
else
up_val = prev_p[x];
if (cur_p[x] > 0) {
//current pixel is foreground and has no connected neighbors
if (left_val == 0 && up_val == 0) {
frame_label[cur_idx] = (int)labels.add();
root_map[frame_label[cur_idx]] = -1;
}
//current pixel is foreground and has left neighbor connected
else if (left_val != 0 && up_val == 0) {
frame_label[cur_idx] = frame_label[left_idx];
}
//current pixel is foreground and has up neighbor connect
else if (up_val != 0 && left_val == 0) {
frame_label[cur_idx] = frame_label[up_idx];
}
//current pixel is foreground and is connected to left and up neighbors
else {
frame_label[cur_idx] = (frame_label[left_idx] > frame_label[up_idx]) ? frame_label[up_idx] : frame_label[left_idx];
labels.unite(frame_label[left_idx], frame_label[up_idx]);
}
}//endif
else {
frame_label[cur_idx] = -1;
}
} //end for x
prev_p = cur_p;
}//end for y
//second loop logic
cur_idx = 0;
int curLabel;
int connCompIdx = 0;
for (y = 0; y < src.size().height; y++ ) {
for (x = 0; x < src.size().width; x++, cur_idx++) {
curLabel = frame_label[cur_idx];
if (curLabel != -1) {
curLabel = labels.find(curLabel);
if( root_map[curLabel] != -1 ) {
cc[root_map[curLabel]].addPixel(x, y);
}
else {
cc.push_back(ConnectedComponent(x,y));
root_map[curLabel] = connCompIdx;
connCompIdx++;
}
}
}//end for x
}//end for y
}
If you don't mind using an external library that uses OpenCV, you can do that using cvBlobsLib.
A library to perform binary images connected component labelling
(similar to regionprops Matlab function). It also provides functions
to manipulate, filter and extract results from the extracted blobs,
see features section for more information.
You can use cv::connectedComponentsWithStats() function.
Here is an example.
// ...
cv::Mat labels, stats, centroids;
int connectivity = 8; // or 4
int label_count = cv::connectedComponentsWithStats(src, labels, stats, centroids, connectivity);
for (int i = 0; i < label_count; i++)
{
int x = stats.at<int>(i, cv::CC_STAT_LEFT);
int y = stats.at<int>(i, cv::CC_STAT_TOP);
int w = stats.at<int>(i, cv::CC_STAT_WIDTH);
int h = stats.at<int>(i, cv::CC_STAT_HEIGHT);
int area = stats.at<int>(i, cv::CC_STAT_AREA);
double cx = centroids.at<double>(i, 0);
double cy = centroids.at<double>(i, 1);
// ...
}
Following DXM's code above which assumes 4-connected components, here is a version for 'findCC' that detects 8-connected components.
void findCC(const cv::Mat& src, std::vector<ConnectedComponent>& cc) {
if (src.empty()) return;
CV_Assert(src.type() == CV_8U);
cc.clear();
int total_pix = int(src.total());
int *frame_label = new int[total_pix];
DisjointSet labels(total_pix);
int *root_map = new int[total_pix];
int x, y;
const uchar* cur_p;
const uchar* prev_p = src.ptr<uchar>(0);
int left_val, up_val, up_left_val, up_right_val;
int cur_idx, left_idx, up_idx, up_left_idx, up_right_idx;
cur_idx = 0;
//first logic loop
for (y = 0; y < src.rows; y++) {
cur_p = src.ptr<uchar>(y);
for (x = 0; x < src.cols; x++, cur_idx++) {
left_idx = cur_idx - 1;
up_idx = cur_idx - src.size().width;
up_left_idx = up_idx - 1;
up_right_idx = up_idx + 1;
if (x == 0)
{
left_val = 0;
}
else
{
left_val = cur_p[x - 1];
}
if (y == 0)
{
up_val = 0;
}
else
{
up_val = prev_p[x];
}
if (x == 0 || y == 0)
{
up_left_val = 0;
}
else
{
up_left_val = prev_p[x-1];
}
if (x == src.cols - 1 || y == 0)
{
up_right_val = 0;
}
else
{
up_right_val = prev_p[x+1];
}
if (cur_p[x] > 0) {
//current pixel is foreground and has no connected neighbors
if (left_val == 0 && up_val == 0 && up_left_val == 0 && up_right_val == 0) {
frame_label[cur_idx] = (int)labels.add();
root_map[frame_label[cur_idx]] = -1;
}
//Current pixel is foreground and has at least one neighbor
else
{
vector<int> frame_lbl;
frame_lbl.reserve(4);
//Find minimal label
int min_frame_lbl = INT_MAX;
int valid_entries_num = 0;
if (left_val != 0)
{
frame_lbl.push_back(frame_label[left_idx]);
min_frame_lbl = min(min_frame_lbl, frame_label[left_idx]);
valid_entries_num++;
}
if (up_val != 0)
{
frame_lbl.push_back(frame_label[up_idx]);
min_frame_lbl = min(min_frame_lbl, frame_label[up_idx]);
valid_entries_num++;
}
if (up_left_val != 0)
{
frame_lbl.push_back(frame_label[up_left_idx]);
min_frame_lbl = min(min_frame_lbl, frame_label[up_left_idx]);
valid_entries_num++;
}
if (up_right_val != 0)
{
frame_lbl.push_back(frame_label[up_right_idx]);
min_frame_lbl = min(min_frame_lbl, frame_label[up_right_idx]);
valid_entries_num++;
}
CV_Assert(valid_entries_num > 0);
frame_label[cur_idx] = min_frame_lbl;
//Unite if necessary
if (valid_entries_num > 1)
{
for (size_t i = 0; i < frame_lbl.size(); i++)
{
labels.unite(frame_lbl[i], min_frame_lbl);
}
}
}
}//endif
else {
frame_label[cur_idx] = -1;
}
} //end for x
prev_p = cur_p;
}//end for y
//second loop logic
cur_idx = 0;
int curLabel;
int connCompIdx = 0;
for (y = 0; y < src.size().height; y++) {
for (x = 0; x < src.size().width; x++, cur_idx++) {
curLabel = frame_label[cur_idx];
if (curLabel != -1) {
curLabel = labels.find(curLabel);
if (root_map[curLabel] != -1) {
cc[root_map[curLabel]].addPixel(x, y);
}
else {
cc.push_back(ConnectedComponent(x, y));
root_map[curLabel] = connCompIdx;
connCompIdx++;
}
}
}//end for x
}//end for y
//Free up allocated memory
delete[] frame_label;
delete[] root_map;
}

Monogame Breakout: having trouble with adding abilities like longer paddle or more balls

I'm gonna add some abilities to random blocks, u know that drops down when you hit a random block. Like you get 2 balls or bigger paddle or slower ball speed.
I need help with writing the for loop and if-statement that can add some abilities to my block levels. Like 1 random ability on level 1 and so on. So when you hit 1 random block of like 20 blocks, that has my ability. It would drop down to the paddle like the original breakout game.
I was thinking of a switch, if one random block with ability is hit and using that switch and randomize it.
void PowerUp()
{
powerups.Add(abilityballs_rect);
powerups.Add(abilitylong_rect);
powerups.Add(abilityslow_rect);
}
-
List<Rectangle> block = new List<Rectangle>();
List<Rectangle> block2 = new List<Rectangle>();
List<Rectangle> block3 = new List<Rectangle>();
List<Rectangle> block4 = new List<Rectangle>();
List<Rectangle> block5 = new List<Rectangle>();
List<Rectangle> block6 = new List<Rectangle>();
List<Rectangle> powerups = new List<Rectangle>();
-
if (level == 1)
{
if (block.Count == 14 && block2.Count == 14)
{
spriteBatch.DrawString(spritefont2, "LEVEL " + level, new Vector2(252, 400), Color.White);
}
foreach (Rectangle g in block)
{
spriteBatch.Draw(block_texture, g, Color.LimeGreen);
}
foreach (Rectangle r in block2)
{
spriteBatch.Draw(block_texture, r, Color.IndianRed);
}
}
else if (level == 2)
{
if (block3.Count == 18 && block4.Count == 27)
{
spriteBatch.DrawString(spritefont2, "LEVEL " + level, new Vector2(246, 400), Color.White);
}
foreach (Rectangle b in block3)
{
spriteBatch.Draw(block_texture, b, Color.CornflowerBlue);
}
foreach (Rectangle y in block4)
{
spriteBatch.Draw(block_texture, y, Color.Yellow);
}
}
else if (level == 3)
{
if (block5.Count == 36 && block6.Count == 18)
{
spriteBatch.DrawString(spritefont2, "LEVEL " + level, new Vector2(246, 400), Color.White);
}
foreach (Rectangle o in block5)
{
spriteBatch.Draw(block_texture, o, Color.Orange);
}
foreach (Rectangle p in block6)
{
spriteBatch.Draw(block_texture, p, Color.HotPink);
}
}
-
void AddBlocks()
{
//LEVEL 1
for (int i = 1; i < 3; i++)
{
for (int f = 1; f < 8; f++)
{
block.Add(new Rectangle((f * 63) + 94, (i * 40) + 60, block_texture.Width, block_texture.Height));
}
}
for (int i = 1; i < 3; i++)
{
for (int g = 1; g < 8; g++)
{
block2.Add(new Rectangle((g * 63) + 94, (i * 40) + 40, block_texture.Width, block_texture.Height));
}
}
//LEVEL 2
for (int i = 1; i < 3; i++)
{
for (int j = 1; j < 10; j++)
{
block3.Add(new Rectangle((j * 63) + 34, (i * 200) - 60, block_texture.Width, block_texture.Height));
}
}
for (int i = 1; i < 10; i++)
{
for (int k = 1; k < 4; k++)
{
block4.Add(new Rectangle((k * 103) + 143, (i * 20) + 140, block_texture.Width, block_texture.Height));
}
}
//LEVEL 3
for (int i = 1; i < 7; i++)
{
for (int j = 1; j < 7; j++)
{
block5.Add(new Rectangle((j * 63) + 127, (i * 20) + 190, block_texture.Width, block_texture.Height));
}
}
for (int i = 1; i < 10; i++)
{
for (int k = 1; k < 3; k++)
{
block6.Add(new Rectangle((k * 443) - 317, (i * 20) + 160, block_texture.Width, block_texture.Height));
}
}
}
-
void DeleteBlocks()
{
if (level == 1)
{
for (int j = 0; j < block.Count; j++)
{
if (ball_rect.Intersects(block[j]))
{
ball_speed.Y *= -1;
points += 1;
block.RemoveAt(j);
if (points > highscore)
{
highscore = points;
}
}
}
for (int k = 0; k < block2.Count; k++)
{
if (ball_rect.Intersects(block2[k]))
{
ball_speed.Y *= -1;
points += 1;
block2.RemoveAt(k);
if (points > highscore)
{
highscore = points;
}
}
}
if (block.Count == 0 && block2.Count == 0)
{
level++;
StartValueBallPaddle();
Start = false;
}
}
else if (level == 2)
{
for (int l = 0; l < block3.Count; l++)
{
if (ball_rect.Intersects(block3[l]))
{
ball_speed.Y *= -1;
points += 1;
block3.RemoveAt(l);
if (points > highscore)
{
highscore = points;
}
}
}
for (int m = 0; m < block4.Count; m++)
{
if (ball_rect.Intersects(block4[m]))
{
ball_speed.Y *= -1;
points += 1;
block4.RemoveAt(m);
if (points > highscore)
{
highscore = points;
}
}
}
if (block3.Count == 0 && block4.Count == 0)
{
level++;
StartValueBallPaddle();
Start = false;
}
}
else if (level == 3)
{
for (int n = 0; n < block5.Count; n++)
{
if (ball_rect.Intersects(block5[n]))
{
ball_speed.Y *= -1;
points += 1;
block5.RemoveAt(n);
if (points > highscore)
{
highscore = points;
}
}
}
for (int o = 0; o < block6.Count; o++)
{
if (ball_rect.Intersects(block6[o]))
{
ball_speed.Y *= -1;
points += 1;
block6.RemoveAt(o);
if (points > highscore)
{
highscore = points;
}
}
}
}
}
You might want to encapsulate your block data into a class, containing the color, the position and powerup of the block.
You could have a method inside that would be called "AddPowerup()" or something, this method will be used to add a random (or specific) powerup to the block. You'll maybe need a getter for your powerup.
Now in your game, you would hold all the blocks of a level inside a list, or a 2d array, or any collection that suits you
Then, to apply powerup to random blocks in the level, you could do something like this (mostly pseudo code, so not tested) :
List<Block> blockList = CreateBlockLevel(1);
int randomIndex = new Random().Next(blockList.Length-1);
blockList[randomIndex].AddPowerup();
If you want to apply a powerup to multiple blocks, you can put that in a for-loop, but then you might want to check if the block has already a powerup or not.

Finding the points nearest to the edge of a irregular shape inside a cicle c++

bool cancelFlag = true;
bool useUserSelectionForSubplugs = false;
bool allowMultipleDevicesInOneDieFlag = false;
int diesToSearchX, diesToSearchY;
diesToSearchX = diesToSearchY = 2;
PBEdgeInterpolationWindow *edgeInterpolationWindow = new PBEdgeInterpolationWindow(&diesToSearchX, &diesToSearchY, &useUserSelectionForSubplugs, &allowMultipleDevicesInOneDieFlag, &cancelFlag);
edgeInterpolationWindow->exec();
if(cancelFlag) return;
if(fSelectedDeviceList.empty())
{
QMessageBox::warning(this, tr("Edge Crown Creation"), tr("Nothing to create crown with: only the devices in Selected Devices List will be considered for this operation\nPlease add devices to the \"Selected Devices\" list"));
return;
}
PBWaferMapRevision *pendingRevision = fData->fPending_Revision;
if(!pendingRevision)
{
QMessageBox::warning(this, tr("Edge Crown Creation"), tr("Revision to be edited needs to be a PENDING revision"));
return;
}
struct WMDeviceForCrown
{
double x, y;
double wrtShotX, wrtShotY;
int crownShotRow, crownShotCol;
WaferDevice *WaferDevicePointer;
};
std::vector<WMDeviceForCrown> DeviceForCrownList;
PBProductData *productData = static_cast<PBProductData*>(fData->Getparent()->Getparent());
double offsetX = productData->fOffsetX;
double offsetY = productData->fOffsetY;
double diesizeX = productData->fDieSizeX;
double diesizeY = productData->fDieSizeY;
/* Collect all devices within the edges, assign them coordinates of their first probe */
if(useUserSelectionForSubplugs )
{
qDebug()<<"inside if crown";
bool noSubplugSelected = true;
for(int i=0; i<pendingRevision->fShotList.size(); i++)
{
for(int j=0; j<pendingRevision->fShotList[i].fSubPlugList.size(); j++)
{
if(pendingRevision->fShotList[i].fSubPlugList[j].fIsSelected)
{
noSubplugSelected = false;
PBSubPlug *subPlug = fCurrentRevision->fShotList[i].fSubPlugList[j].fSubPlug;
for(int k=0; k<pendingRevision->fShotList[i].fDeviceList.size(); k++)
{
WaferDevice *dev = &(pendingRevision->fShotList[i].fDeviceList[k]);
if(!dev->fIsOutsideEE)
{
if(std::find(fSelectedDeviceList.begin(), fSelectedDeviceList.end(), dev->fDevice) != fSelectedDeviceList.end())
{
double probeX = dev->fDevice->fDevice->fMPFProbeList->fProbeList.front()->fProbe_pos_x;
double probeY = dev->fDevice->fDevice->fMPFProbeList->fProbeList.front()->fProbe_pos_y;
double x = subPlug->fSubplgx;
double y = subPlug->fSubplgy;
double w = subPlug->fSubplgwidth;
double h = subPlug->fSubplgheight;
if((probeX > x-kDoubleTolerence) && (probeX < x+w+kDoubleTolerence) && (probeY > y-kDoubleTolerence) && (probeY < y+h+kDoubleTolerence))
{
WMDeviceForCrown devForCrown;
devForCrown.WaferDevicePointer = dev;
double shotX = pendingRevision->fShotList[i].fShot->fShotX;
double shotY = pendingRevision->fShotList[i].fShot->fShotY;
devForCrown.wrtShotX = probeX;
devForCrown.wrtShotY = probeY;
if(dev->fDevice->fDevice->fMPFProbeList->fProbeList.empty()) return;
double probe1X = shotX + devForCrown.wrtShotX;
double probe1Y = shotY + devForCrown.wrtShotY;
devForCrown.x = probe1X;
devForCrown.y = probe1Y;
devForCrown.crownShotRow= pendingRevision->fShotList[i].fShot->fShotRow;
devForCrown.crownShotCol= pendingRevision->fShotList[i].fShot->fShotCol;
DeviceForCrownList.push_back(devForCrown);
//break;
}
}
}
}
}
}
}
if(noSubplugSelected)
{
QMessageBox::warning(this, tr("Edge Crown Creation"), tr("Nothing to create crown with: only the selected devices in selected subplugs will be considered for this operation\nPlease select one or more subplugs in the wafer map\nor uncheck option \"consider devices only in selected subplugs\""));
return;
}
}
else
{
qDebug()<<"inside else crown";
for(int i=0; i<pendingRevision->fShotList.size(); i++)
{
if(pendingRevision->fShotList[i].fShot->fShotName == "Std shots")
{
for(int j=0; j<pendingRevision->fShotList[i].fDeviceList.size(); j++)
{
WaferDevice *dev = &(pendingRevision->fShotList[i].fDeviceList[j]);
if(std::find(fSelectedDeviceList.begin(), fSelectedDeviceList.end(), dev->fDevice)==fSelectedDeviceList.end()) continue;
if(!dev->fIsOutsideEE)
{
WMDeviceForCrown devForCrown;
devForCrown.WaferDevicePointer = dev;
double shotX = pendingRevision->fShotList[i].fShot->fShotX;
double shotY = pendingRevision->fShotList[i].fShot->fShotY;
devForCrown.wrtShotX = dev->fDevice->fDevice->fMPFProbeList->fProbeList.front()->fProbe_pos_x;
devForCrown.wrtShotY = dev->fDevice->fDevice->fMPFProbeList->fProbeList.front()->fProbe_pos_y;
if(dev->fDevice->fDevice->fMPFProbeList->fProbeList.empty()) return;
double probe1X = shotX + devForCrown.wrtShotX;
double probe1Y = shotY + devForCrown.wrtShotY;
devForCrown.x = probe1X;
devForCrown.y = probe1Y;
devForCrown.crownShotRow= pendingRevision->fShotList[i].fShot->fShotRow;
devForCrown.crownShotCol= pendingRevision->fShotList[i].fShot->fShotCol;
DeviceForCrownList.push_back(devForCrown);
// break;
}
}
}
}
}
if(DeviceForCrownList.empty())
{
QMessageBox::warning(this, tr("Edge Crown Creation"), tr("No valid devices for the crown operation. \nNo device from selected devices list could be found in the selected subplugs."));
return;
}
std::vector<WMDeviceForCrown> DeviceOnEdgeList;
for(int i=0; i<DeviceForCrownList.size(); i++)
{
WMDeviceForCrown dev = DeviceForCrownList[i];
bool quadrantEmpty;
/* Axes as thick as diesize */
int xOffset = int(dev.wrtShotX)%int(diesizeX);
int xReminder = diesizeX - xOffset;
double xmin = dev.x - xOffset;
double xmax = dev.x + xReminder;
int yOffset = int(dev.wrtShotY)%int(diesizeY);
int yReminder = diesizeY - yOffset;
double ymin = dev.y - yOffset;
double ymax = dev.y + yReminder;
/* First Quadrant */
quadrantEmpty = true;
for(int j=0; j<DeviceForCrownList.size(); j++)
{
if(i!=j)
{
if((DeviceForCrownList[j].x>xmax && DeviceForCrownList[j].y>ymax) )
{
/*if((DeviceForCrownList[j].y>ymax && DeviceForCrownList[j].x>=xmin && DeviceForCrownList[j].x<=xmax))
{
DeviceOnEdgeList.push_back(dev);
continue;
}*/
/*qDebug()<<"xmin::"<<xmin;
qDebug()<<"xmax::"<<xmax;
qDebug()<<"ymin::"<<ymin;
qDebug()<<"ymax::"<<ymax;
*/
quadrantEmpty = false;
break;
}
}
}
if(quadrantEmpty)
{
DeviceOnEdgeList.push_back(dev);
continue;
}
//* Second Quadrant */
quadrantEmpty = true;
for(int j=0; j<DeviceForCrownList.size(); j++)
{
if(i!=j)
{
if(DeviceForCrownList[j].x<xmin && DeviceForCrownList[j].y>ymax /*|| (DeviceForCrownList[j].x<xmin && DeviceForCrownList[j].y>=ymin && DeviceForCrownList[j].y<=ymax*/)
{
quadrantEmpty = false;
break;
}
}
}
if(quadrantEmpty)
{
DeviceOnEdgeList.push_back(dev);
continue;
}
//* Third Quadrant */
quadrantEmpty = true;
for(int j=0; j<DeviceForCrownList.size(); j++)
{
if(i!=j)
{
if(DeviceForCrownList[j].x<xmin && DeviceForCrownList[j].y<ymin)
{
quadrantEmpty = false;
break;
}
}
}
if(quadrantEmpty)
{
DeviceOnEdgeList.push_back(dev);
continue;
}
//
/////* Fourth Quadrant */
quadrantEmpty = true;
for(int j=0; j<DeviceForCrownList.size(); j++)
{
if(i!=j)
{
if((DeviceForCrownList[j].x>xmax && DeviceForCrownList[j].y<ymin) /*|| (DeviceForCrownList[j].x<xmax && DeviceForCrownList[j].y>ymin)*/)
{
quadrantEmpty = false;
break;
}
}
}
if(quadrantEmpty)
{
DeviceOnEdgeList.push_back(dev);
continue;
}
// /* Along X-Positive Axis */
quadrantEmpty = true;
for(int j=0; j<DeviceForCrownList.size(); j++)
{
if(i!=j)
{
if(DeviceForCrownList[j].x>xmax && DeviceForCrownList[j].y>=ymin && DeviceForCrownList[j].y<=ymax)
{
quadrantEmpty = false;
break;
}
}
}
if(quadrantEmpty)
{
DeviceOnEdgeList.push_back(dev);
continue;
}
//// ///* Along Y-Positive Axis */
quadrantEmpty = true;
for(int j=0; j<DeviceForCrownList.size(); j++)
{
if(i!=j)
{
if((DeviceForCrownList[j].y>ymax && DeviceForCrownList[j].x>=xmin && DeviceForCrownList[j].x<=xmax) /*&& (DeviceForCrownList[j].x>xmax && DeviceForCrownList[j].y>=ymin && DeviceForCrownList[j].y<=ymax)*/ )
{
quadrantEmpty = false;
break;
}
}
}
if(quadrantEmpty)
{
DeviceOnEdgeList.push_back(dev);
continue;
}
////
// ///* Along X-Negative Axis */
quadrantEmpty = true;
for(int j=0; j<DeviceForCrownList.size(); j++)
{
if(i!=j)
{
if(DeviceForCrownList[j].x<xmin && DeviceForCrownList[j].y>=ymin && DeviceForCrownList[j].y<=ymax)
{
quadrantEmpty = false;
break;
}
}
}
if(quadrantEmpty)
{
DeviceOnEdgeList.push_back(dev);
continue;
}
///////* Along Y-Negative Axis */
quadrantEmpty = true;
for(int j=0; j<DeviceForCrownList.size(); j++)
{
if(i!=j)
{
if(DeviceForCrownList[j].y<ymin && DeviceForCrownList[j].x>=xmin && DeviceForCrownList[j].x<=xmax)
{
quadrantEmpty = false;
break;
}
}
}
if(quadrantEmpty)
{
DeviceOnEdgeList.push_back(dev);
continue;
}
}
if(DeviceForCrownList.empty())
{
QMessageBox::warning(this, tr("Edge Crown Creation"), tr("No valid devices found along the edge"));
return;
}
/* Temporary code for visualization */
//for(int i=0; i<DeviceOnEdgeList.size(); i++)
//{
// QGraphicsEllipseItem *itm = new QGraphicsEllipseItem(DeviceOnEdgeList[i].x-150, -DeviceOnEdgeList[i].y-150, 300, 300);
// itm->setBrush(Qt::blue);
// fWaferMapView.scene()->addItem(itm);
//}
I have a circle in 2d plane with centre as 0,0 .
Now i have drawn rectangles of fixed sizes all over the circle , rectangle 0,0 is the one which contains centre of circle and then rectangle 0,1 ,02 so on are along x, axis and similarly in all Quadrants.
Now each rectangle has some devices and i knw the x,y of those devices for each rectangle. each rectangle has same devices in it.
Now i am selecting the devices in grey as per this picture:
https://docs.google.com/file/d/0B_oYS4i7-wQMWldWdzRjcG1qekU/edit?usp=drive_web&pli=1
now when i run the above code , I am trying to select the devices at the edges of the selection in grey like this :
https://drive.google.com/file/d/0B_oYS4i7-wQMc0x2cFhSMWE0SmM/view?usp=sharing
but still, some devices are not selected as per this link (see red circle).
so need some help/logic to achieve the same.
Thanks in advance!

SDL_Rect not visible

I have multiple SDL_Rects creating a snake that is supposed to stay in a specific area. Sometimes when the "snake" reaches the boundaries a part disappears.
void Snake::update(SDL_Surface *screen, int level)
{
old_pos.first = snake_rect[0];
if(x_axis)
snake_rect[0].x += snake_speed * level * direction_multiplier;
else if(!x_axis)
snake_rect[0].y += snake_speed * level * direction_multiplier;
for(unsigned int i = 1; i < snake_rect.size(); ++i)
{
old_pos.second = snake_rect[i];
snake_rect[i] = old_pos.first;
old_pos.first = old_pos.second;
}
boundariesCheck(screen);
/// Making the enemy move randomly
if(rand() % 100 < 10)
{
if(x_axis)
{
x_axis = false;
direction.second = rand() % 2;
if(direction.second)
direction_multiplier = 1;
else if(!direction.second)
direction_multiplier = -1;
}
else if(!x_axis)
{
x_axis = true;
direction.first = rand() % 2;
if(direction.first)
direction_multiplier = 1;
else if(!direction.first)
direction_multiplier = -1;
}
}
}
void Snake::draw(SDL_Surface *screen)
{
for(unsigned int i = 1; i < snake_rect.size(); ++i)
{
SDL_FillRect(screen, &snake_rect[i], 0xFF0000);
}
SDL_FillRect(screen, &snake_rect[0], 0xFF5500);
}

connected components in OpenCV

I am looking for an OpenCV function that can find connected components and perform a few tasks on them ( like getting the number of pixels, contour, list of pixels in the object etc.. )
Is there a function of OpenCV (C++) that is similar to MatLab's regionprops ?
Starting from version 3.0, OpenCV has connectedComponents function.
Have a look at the cvFindContours function. It's very versatile -- it can find both interior and exterior contours, and return the results in a variety of formats (e.g. flat list vs. tree structure). Once you have the contours, functions like cvContourArea allow you to determine basic properties of the connected component corresponding to a particular contour.
If you prefer to use the newer C++ interface (as opposed to the older C-style interface I described above), then the function names are similar.
set -std=c++0x option when compiling
.h file
//connected_components.h
#ifndef CONNECTED_COMPONENTS_H_
#define CONNECTED_COMPONENTS_H_
#include <opencv2/core/core.hpp>
#include <memory>
class DisjointSet {
private:
std::vector<int> m_disjoint_array;
int m_subset_num;
public:
DisjointSet();
DisjointSet(int size);
~DisjointSet();
int add(); //add a new element, which is a subset by itself;
int find(int x); //return the root of x
void unite(int x, int y);
int getSubsetNum(void);
};
class ConnectedComponent {
private:
cv::Rect m_bb;
int m_pixel_count;
std::shared_ptr< std::vector<cv::Point2i> > m_pixels;
public:
ConnectedComponent();
ConnectedComponent(int x, int y);
~ConnectedComponent();
void addPixel(int x, int y);
int getBoundingBoxArea(void) const;
cv::Rect getBoundingBox(void) const;
int getPixelCount(void) const;
std::shared_ptr< const std::vector<cv::Point2i> > getPixels(void) const;
};
void findCC(const cv::Mat& src, std::vector<ConnectedComponent>& cc);
#endif //CONNECTED_COMPONENTS_H_
.cc file
//connected_components.cpp
#include "connected_components.h"
using namespace std;
/** DisjointSet **/
DisjointSet::DisjointSet() :
m_disjoint_array(),
m_subset_num(0)
{ }
DisjointSet::DisjointSet(int size) :
m_disjoint_array(),
m_subset_num(0)
{
m_disjoint_array.reserve(size);
}
DisjointSet::~DisjointSet()
{ }
//add a new element, which is a subset by itself;
int DisjointSet::add()
{
int cur_size = m_disjoint_array.size();
m_disjoint_array.push_back(cur_size);
m_subset_num ++;
return cur_size;
}
//return the root of x
int DisjointSet::find(int x)
{
if (m_disjoint_array[x] < 0 || m_disjoint_array[x] == x)
return x;
else {
m_disjoint_array[x] = this->find(m_disjoint_array[x]);
return m_disjoint_array[x];
}
}
// point the x and y to smaller root of the two
void DisjointSet::unite(int x, int y)
{
if (x==y) {
return;
}
int xRoot = find(x);
int yRoot = find(y);
if (xRoot == yRoot)
return;
else if (xRoot < yRoot) {
m_disjoint_array[yRoot] = xRoot;
}
else {
m_disjoint_array[xRoot] = yRoot;
}
m_subset_num--;
}
int DisjointSet::getSubsetNum()
{
return m_subset_num;
}
/** ConnectedComponent **/
ConnectedComponent::ConnectedComponent() :
m_bb(0,0,0,0),
m_pixel_count(0),
m_pixels()
{
m_pixels = std::make_shared< std::vector<cv::Point2i> > ();
}
ConnectedComponent::ConnectedComponent(int x, int y) :
m_bb(x,y,1,1),
m_pixel_count(1),
m_pixels()
{
m_pixels = std::make_shared< std::vector<cv::Point2i> > ();
}
ConnectedComponent::~ConnectedComponent(void)
{ }
void ConnectedComponent::addPixel(int x, int y) {
m_pixel_count++;
// new bounding box;
if (m_pixel_count == 0) {
m_bb = cv::Rect(x,y,1,1);
}
// extend bounding box if necessary
else {
if (x < m_bb.x ) {
m_bb.width+=(m_bb.x-x);
m_bb.x = x;
}
else if ( x > (m_bb.x+m_bb.width) ) {
m_bb.width=(x-m_bb.x);
}
if (y < m_bb.y ) {
m_bb.height+=(m_bb.y-y);
m_bb.y = y;
}
else if ( y > (m_bb.y+m_bb.height) ) {
m_bb.height=(y-m_bb.y);
}
}
m_pixels->push_back(cv::Point(x,y));
}
int ConnectedComponent::getBoundingBoxArea(void) const {
return (m_bb.width*m_bb.height);
}
cv::Rect ConnectedComponent::getBoundingBox(void) const {
return m_bb;
}
std::shared_ptr< const std::vector<cv::Point2i> > ConnectedComponent::getPixels(void) const {
return m_pixels;
}
int ConnectedComponent::getPixelCount(void) const {
return m_pixel_count;
}
/** find connected components **/
void findCC(const cv::Mat& src, std::vector<ConnectedComponent>& cc) {
if (src.empty()) return;
CV_Assert(src.type() == CV_8U);
cc.clear();
int total_pix = src.total();
int frame_label[total_pix];
DisjointSet labels(total_pix);
int root_map[total_pix];
int x, y;
const uchar* cur_p;
const uchar* prev_p = src.ptr<uchar>(0);
int left_val, up_val;
int cur_idx, left_idx, up_idx;
cur_idx = 0;
//first logic loop
for (y = 0; y < src.rows; y++ ) {
cur_p = src.ptr<uchar>(y);
for (x = 0; x < src.cols; x++, cur_idx++) {
left_idx = cur_idx - 1;
up_idx = cur_idx - src.size().width;
if ( x == 0)
left_val = 0;
else
left_val = cur_p[x-1];
if (y == 0)
up_val = 0;
else
up_val = prev_p[x];
if (cur_p[x] > 0) {
//current pixel is foreground and has no connected neighbors
if (left_val == 0 && up_val == 0) {
frame_label[cur_idx] = (int)labels.add();
root_map[frame_label[cur_idx]] = -1;
}
//current pixel is foreground and has left neighbor connected
else if (left_val != 0 && up_val == 0) {
frame_label[cur_idx] = frame_label[left_idx];
}
//current pixel is foreground and has up neighbor connect
else if (up_val != 0 && left_val == 0) {
frame_label[cur_idx] = frame_label[up_idx];
}
//current pixel is foreground and is connected to left and up neighbors
else {
frame_label[cur_idx] = (frame_label[left_idx] > frame_label[up_idx]) ? frame_label[up_idx] : frame_label[left_idx];
labels.unite(frame_label[left_idx], frame_label[up_idx]);
}
}//endif
else {
frame_label[cur_idx] = -1;
}
} //end for x
prev_p = cur_p;
}//end for y
//second loop logic
cur_idx = 0;
int curLabel;
int connCompIdx = 0;
for (y = 0; y < src.size().height; y++ ) {
for (x = 0; x < src.size().width; x++, cur_idx++) {
curLabel = frame_label[cur_idx];
if (curLabel != -1) {
curLabel = labels.find(curLabel);
if( root_map[curLabel] != -1 ) {
cc[root_map[curLabel]].addPixel(x, y);
}
else {
cc.push_back(ConnectedComponent(x,y));
root_map[curLabel] = connCompIdx;
connCompIdx++;
}
}
}//end for x
}//end for y
}
If you don't mind using an external library that uses OpenCV, you can do that using cvBlobsLib.
A library to perform binary images connected component labelling
(similar to regionprops Matlab function). It also provides functions
to manipulate, filter and extract results from the extracted blobs,
see features section for more information.
You can use cv::connectedComponentsWithStats() function.
Here is an example.
// ...
cv::Mat labels, stats, centroids;
int connectivity = 8; // or 4
int label_count = cv::connectedComponentsWithStats(src, labels, stats, centroids, connectivity);
for (int i = 0; i < label_count; i++)
{
int x = stats.at<int>(i, cv::CC_STAT_LEFT);
int y = stats.at<int>(i, cv::CC_STAT_TOP);
int w = stats.at<int>(i, cv::CC_STAT_WIDTH);
int h = stats.at<int>(i, cv::CC_STAT_HEIGHT);
int area = stats.at<int>(i, cv::CC_STAT_AREA);
double cx = centroids.at<double>(i, 0);
double cy = centroids.at<double>(i, 1);
// ...
}
Following DXM's code above which assumes 4-connected components, here is a version for 'findCC' that detects 8-connected components.
void findCC(const cv::Mat& src, std::vector<ConnectedComponent>& cc) {
if (src.empty()) return;
CV_Assert(src.type() == CV_8U);
cc.clear();
int total_pix = int(src.total());
int *frame_label = new int[total_pix];
DisjointSet labels(total_pix);
int *root_map = new int[total_pix];
int x, y;
const uchar* cur_p;
const uchar* prev_p = src.ptr<uchar>(0);
int left_val, up_val, up_left_val, up_right_val;
int cur_idx, left_idx, up_idx, up_left_idx, up_right_idx;
cur_idx = 0;
//first logic loop
for (y = 0; y < src.rows; y++) {
cur_p = src.ptr<uchar>(y);
for (x = 0; x < src.cols; x++, cur_idx++) {
left_idx = cur_idx - 1;
up_idx = cur_idx - src.size().width;
up_left_idx = up_idx - 1;
up_right_idx = up_idx + 1;
if (x == 0)
{
left_val = 0;
}
else
{
left_val = cur_p[x - 1];
}
if (y == 0)
{
up_val = 0;
}
else
{
up_val = prev_p[x];
}
if (x == 0 || y == 0)
{
up_left_val = 0;
}
else
{
up_left_val = prev_p[x-1];
}
if (x == src.cols - 1 || y == 0)
{
up_right_val = 0;
}
else
{
up_right_val = prev_p[x+1];
}
if (cur_p[x] > 0) {
//current pixel is foreground and has no connected neighbors
if (left_val == 0 && up_val == 0 && up_left_val == 0 && up_right_val == 0) {
frame_label[cur_idx] = (int)labels.add();
root_map[frame_label[cur_idx]] = -1;
}
//Current pixel is foreground and has at least one neighbor
else
{
vector<int> frame_lbl;
frame_lbl.reserve(4);
//Find minimal label
int min_frame_lbl = INT_MAX;
int valid_entries_num = 0;
if (left_val != 0)
{
frame_lbl.push_back(frame_label[left_idx]);
min_frame_lbl = min(min_frame_lbl, frame_label[left_idx]);
valid_entries_num++;
}
if (up_val != 0)
{
frame_lbl.push_back(frame_label[up_idx]);
min_frame_lbl = min(min_frame_lbl, frame_label[up_idx]);
valid_entries_num++;
}
if (up_left_val != 0)
{
frame_lbl.push_back(frame_label[up_left_idx]);
min_frame_lbl = min(min_frame_lbl, frame_label[up_left_idx]);
valid_entries_num++;
}
if (up_right_val != 0)
{
frame_lbl.push_back(frame_label[up_right_idx]);
min_frame_lbl = min(min_frame_lbl, frame_label[up_right_idx]);
valid_entries_num++;
}
CV_Assert(valid_entries_num > 0);
frame_label[cur_idx] = min_frame_lbl;
//Unite if necessary
if (valid_entries_num > 1)
{
for (size_t i = 0; i < frame_lbl.size(); i++)
{
labels.unite(frame_lbl[i], min_frame_lbl);
}
}
}
}//endif
else {
frame_label[cur_idx] = -1;
}
} //end for x
prev_p = cur_p;
}//end for y
//second loop logic
cur_idx = 0;
int curLabel;
int connCompIdx = 0;
for (y = 0; y < src.size().height; y++) {
for (x = 0; x < src.size().width; x++, cur_idx++) {
curLabel = frame_label[cur_idx];
if (curLabel != -1) {
curLabel = labels.find(curLabel);
if (root_map[curLabel] != -1) {
cc[root_map[curLabel]].addPixel(x, y);
}
else {
cc.push_back(ConnectedComponent(x, y));
root_map[curLabel] = connCompIdx;
connCompIdx++;
}
}
}//end for x
}//end for y
//Free up allocated memory
delete[] frame_label;
delete[] root_map;
}