I am using Win 7,64, MS2012(C++) and OpenCV 2.4.11
I write seeded region growing algorithm but I down't know why the results not desired.
The goal is that extract pectoral muscle(left corner) of image with SRG algorithm.
input image :
here is my code (main function)
img = imread("C:/Users/Zimabi/Downloads/region_growing/jhgray.jpg",0);
Mat J1 = Mat::zeros(img.rows,img.cols,CV_8UC1);
int x=15,y=15;
int reg_mean = img.at<uchar>(x,y);
int reg_size = 1;
int neg_pos = 0;
Mat neg_list = Mat::zeros(img.cols*img.rows,3,CV_8UC1);
double pixdist = 0, reg_maxdist = 0.1;
int xn = 0,yn = 0;
Mat neigb = Mat::zeros(4,2,CV_8UC1);
int nei1 [4] = {-1,1,0,0};
int nei2 [4] = {0,0,-1,1};
while ((pixdist < reg_maxdist) && (reg_size < img.cols*img.rows))
{
int inx,min1=1000;
for (int r = 0; r < 4; r++)
{
xn = x + nei1[r] ;
yn = y + nei2[r];
bool ins=(xn>=1)&&(yn>=1)&&(xn<=img.rows)&&(yn<= img.cols);
if (ins && (J1.at<uchar>(xn,yn) == 0))
{
neg_pos = neg_pos+1;
neg_list.at<uchar>(neg_pos,0) = xn;
neg_list.at<uchar>(neg_pos,1) = yn;
neg_list.at<uchar>(neg_pos,2) = img.at<uchar>(xn,yn);
J1.at<uchar>(xn,yn)=255;
}
}
Mat x1 = Mat::zeros(neg_pos,1,CV_8UC1);
for (int i3 = 0; i3 <neg_pos ; i3++)
{
x1.at<uchar>(i3,0) = abs(neg_list.at<uchar>(i3,2) - reg_mean);
if (x1.at<uchar>(i3,0)<min1)
{
min1 = x1.at<uchar>(i3,0);
inx = i3;
}
}
pixdist = min1;
J1.at<uchar>(x,y)=255;
reg_size=reg_size+1;
reg_mean= (reg_mean*reg_size + neg_list.at<uchar> (inx,2))/(reg_size+1);
x = neg_list.at<uchar>(inx,0);
y = neg_list.at<uchar>(inx,1);
neg_list.at<uchar>(inx,0) = neg_list.at<uchar>(neg_pos,0);
neg_list.at<uchar>(inx,1) = neg_list.at<uchar>(neg_pos,1);
neg_list.at<uchar>(inx,2) = neg_list.at<uchar>(neg_pos,2);
neg_pos=neg_pos-1;
}
imshow("J",J1);
waitKey(0);
return 0;
Regards
Related
I managed with some help to know how when two rectangles are intersecting each other, from there it should be easy to make what i just said in the title but ...
So, short story of what i just did below:
Created a for loop from 1 to Number_of_Obstacles
In that for an random obstacle (rectangle/square) is created and it will be checked if it is overlaped with all other obstacles created from 0 to the loop contor (or in other words every obstacle stored in the vector)
Again, the doOverLap function works. Tested it with a square which i made a controller and other random rectangle created on the screen. It outputs in chat when i'm overlaping it and trust me, i overlaped it from all angles.
Here is a picture with the overlaping issue: https://imgur.com/a/ZzorOcD
bool doOverlap(A a, B b)
{
if (a.x1 > b.x2 || b.x1 > a.x2)
return false;
if (a.y1 > b.y2 || b.y1 > a.y2)
return false;
return true;
}
struct Obstacles {
int X, Y;
void Create_Random_Obstacles(Obstacles Obj[], int Numar_Obstacole)
{
srand(time(NULL));
A Rectangle_1;
B Rectangle_2;
/* To avoid rendering outside of the screen */
int X_Axis = X_RESOLUTION - 40;
int Y_Axis = Y_RESOLUTION - 40;
int obstacolX = rand() % X_Axis + 1;
int obstacolY = rand() % Y_Axis + 1;
Obj[0].X = obstacolX;
Obj[0].Y = obstacolY;
for (int i = 1; i < Numar_Obstacole; i++)
{
obstacolX = rand() % X_Axis + 1;
obstacolY = rand() % Y_Axis + 1;
Rectangle_1.x1 = obstacolX;
Rectangle_1.x2 = obstacolX + 40;
Rectangle_1.y1 = obstacolY;
Rectangle_1.y2 = obstacolY + 40;
for (int j = 0; j < i; j++) {
Rectangle_2.x1 = Obj[j].X;
Rectangle_2.x2 = Obj[j].X + 40;
Rectangle_2.y1 = Obj[j].Y;
Rectangle_2.y2 = Obj[j].Y + 40;
if (doOverlap(Rectangle_1, Rectangle_2))
{
std::cout << "Overlap\n";
}
else
{
Obj[i].X = obstacolX;
Obj[i].Y = obstacolY;
}
}
}
}
void Render(SDL_Renderer* renderer, Obstacles Obj[], int Numar_Obstacole) {
for (int i = 0; i < Numar_Obstacole; i++)
{
SDL_Rect r{ Obj[i].X, Obj[i].Y, 40, 40 };
SDL_SetRenderDrawColor(renderer, 255, 160, 15, 255);
SDL_RenderFillRect(renderer, &r);
}
}
};
Restart selection when collision occurs, something like:
bool Has_Overlap(const Obstacles& obj, const Obstacles* Objs, int Size)
{
B Rectangle_2;
Rectangle_2.x1 = obs.X;
Rectangle_2.x2 = obs.X + 40;
Rectangle_2.y1 = obs.Y;
Rectangle_2.y2 = obs.Y + 40;
for (int i = 0; i != Size; ++i) {
A Rectangle_1;
Rectangle_1.x1 = Obs[i].X;
Rectangle_1.x2 = Obs[i].X + 40;
Rectangle_1.y1 = Obs[i].Y;
Rectangle_1.y2 = Obs[i].Y + 40;
if (doOverlap(Rectangle_1, Rectangle_2)) {
return true;
}
}
return false;
}
void Create_Random_Obstacles(Obstacles* Objs, int Size)
{
/* To avoid rendering outside of the screen */
const int X_Axis = X_RESOLUTION - 40;
const int Y_Axis = Y_RESOLUTION - 40;
for (int i = 0; i < Size; i++)
{
do {
Objs[i].X = rand() % X_Axis + 1;
Objs[i].Y = rand() % Y_Axis + 1;
} while (Has_Overlap(Objs[i], Objs, i));
}
}
I have tried the new OpenCV edge boxes implementation. I ran the edgeboxes_demo program from OpenCV ximgproc samples and it causes the following assertion failure.
OpenCV(3.4.1) Error: Assertion failed ((unsigned)(i1 *
DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels())) in
cv::Mat::at, file
C:\OpenCV\opencv-3.4.1\modules\core\include\opencv2/core/mat.inl.hpp,
line 1107
Tried to follow the error and found that it was caused by the prepDataStructsfuntion of the edge boxes class. The code of the function is given below.
I have tried changing
for (i = 0; i < n; i++) _sDone.at<int>(0,i) = -1;
to
for (i = 0; i < n; i++) _sDone.at<int>(i,0) = -1;
but the problem remains.
void EdgeBoxesImpl::prepDataStructs(Mat &edgeMap)
{
int y, x, i;
// create _segIImg
Mat E1 = Mat::zeros(w, h, DataType<float>::type);
for (i=0; i < _segCnt; i++)
{
if (_segMag[i] > 0) E1.at<float>(_segP[i].x, _segP[i].y) = _segMag[i];
}
_segIImg = Mat::zeros(w+1, h+1, DataType<float>::type);
_magIImg = Mat::zeros(w+1, h+1, DataType<float>::type);
for (x=1; x < w; x++)
{
const float *e_ptr = edgeMap.ptr<float>(x);
const float *e1_ptr = E1.ptr<float>(x);
const float *si0_ptr = _segIImg.ptr<float>(x);
float *si1_ptr = _segIImg.ptr<float>(x+1);
const float *mi0_ptr = _magIImg.ptr<float>(x);
float *mi1_ptr =_magIImg.ptr<float>(x+1);
for (y=1; y < h; y++)
{
// create _segIImg
si1_ptr[y+1] = e1_ptr[y] + si0_ptr[y+1] + si1_ptr[y] - si0_ptr[y];
float e = e_ptr[y] > _edgeMinMag ? e_ptr[y] : 0;
// create _magIImg
mi1_ptr[y+1] = e +mi0_ptr[y+1] + mi1_ptr[y] - mi0_ptr[y];
}
}
// create remaining data structures
int s = 0;
int s1;
_hIdxs.resize(h);
_hIdxImg = Mat::zeros(w, h, DataType<int>::type);
for (y = 0; y < h; y++)
{
s = 0;
_hIdxs[y].push_back(s);
for (x = 0; x < w; x++)
{
s1 = _segIds.at<int>(x, y);
if (s1 != s)
{
s = s1;
_hIdxs[y].push_back(s);
}
_hIdxImg.at<int>(x, y) = (int)_hIdxs[y].size() - 1;
}
}
_vIdxs.resize(w);
_vIdxImg = Mat::zeros(w, h, DataType<int>::type);
for (x = 0; x < w; x++)
{
s = 0;
_vIdxs[x].push_back(s);
for (y = 0; y < h; y++)
{
s1 = _segIds.at<int>(x, y);
if (s1 != s)
{
s = s1;
_vIdxs[x].push_back(s);
}
_vIdxImg.at<int>(x, y) = (int)_vIdxs[x].size() - 1;
}
}
// initialize scoreBox() data structures
int n = _segCnt + 1;
_sWts = Mat::zeros(n, 1, DataType<float>::type);
_sDone = Mat::zeros(n, 1, DataType<int>::type);
_sMap = Mat::zeros(n, 1, DataType<int>::type);
_sIds = Mat::zeros(n, 1, DataType<int>::type);
for (i = 0; i < n; i++) _sDone.at<int>(0, i) = -1;
_sId = 0;
}
After changing in the src file it is required to rebuild the OpenCV library and link it to the project.
here is the matlab code i'm trying to convert to c++
where
size(Iorig) == 1334X 2026
%% label checkers
Label = zeros(size(Iorig));
Margins = 11;
[X,Y] = meshgrid(1:size(Iorig,2),1:size(Iorig,1));
k = 1;
for i = 1:4
for j = 1:6
rr = rect{i,j};
x1 = rr(1);
x2 = rr(1) + rr(3);
y1 = rr(2);
y2 = rr(2) + rr(4);
Label(X>=x1+Margins&X<x2-Margins&Y>=y1+Margins&Y<y2-Margins) = k;
k = k+1;
end
end
I understand that we want to label the rectangles which are found in the previous step, there are 24 of those.
but I don't understand how to convert this line into easy c++ code without allocating a huge buffer of X and Y which basically just holds... indices..
thanks for your help here is what i started doing.
//label Checkers
List<List<int>^>^ label = gcnew List<List<int>^>();
int margins = 11;
int k = 1;
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 6; j++)
{
MacbethCheckerBatchesColor^ rect = autoDetectMacbethResult[i * 6 + j];
Point^ r = rect->Points[0];
int x1 = r->X;
int y1 = r->Y;
r = rect->Points[2];
int x2 = r->X;
int y2 = r->Y;
for (int h = 0; h < inputImage->HeightLines; h++)
{
List<int>^ tempRow = gcnew List<int>();
for (int w = 0; w < inputImage->WidthColumns; w++)
{
if ( (w>= x1+margins) & (w<x2-margins) & (h >= y1+margins) & (h<y2-margins) )
{
tempRow->Add(k);
}
else
{
tempRow->Add(0);
}
}
label->Add(tempRow);
}
k= k+100;//i tried here many other numbers... same result
}
}
Here is my result can you please help me find my mistake, the rectangles are the same, I guesss I have some other logical mistake.
I'm doing some debugging and so I'm dumping image files to look at the predictions and transformations.
I can create a caffe::Datum from cv::Mat:
cv::Mat matrix;
// ... initialize matrix
caffe::Datum datum;
caffe::CVMatToDatum(matrix, &datum)
but how do I create a cv::Mat from caffe::Datum? The following code gives the fatal exception "Datum not encoded":
caffe::Datum datum;
// ... initialize datum
cv::Mat matrix;
matrix = DecodeDatumToCVMat(datum, true);
You can use following functions.
cv::Mat DatumToCVMat(const Datum& datum){
int datum_channels = datum.channels();
int datum_height = datum.height();
int datum_width = datum.width();
string strData = datum.data();
cv::Mat cv_img;
if (strData.size() != 0)
{
cv_img.create(datum_height, datum_width, CV_8UC(datum_channels));
const string& data = datum.data();
std::vector<char> vec_data(data.c_str(), data.c_str() + data.size());
for (int h = 0; h < datum_height; ++h) {
uchar* ptr = cv_img.ptr<uchar>(h);
int img_index = 0;
for (int w = 0; w < datum_width; ++w) {
for (int c = 0; c < datum_channels; ++c) {
int datum_index = (c * datum_height + h) * datum_width + w;
ptr[img_index++] = static_cast<uchar>(vec_data[datum_index]);
}
}
}
}
else
{
cv_img.create(datum_height, datum_width, CV_32FC(datum_channels));
for (int h = 0; h < datum_height; ++h) {
float* ptr = cv_img.ptr<float>(h);
int img_index = 0;
for (int w = 0; w < datum_width; ++w) {
for (int c = 0; c < datum_channels; ++c) {
ptr[img_index++] = static_cast<float>(datum.float_data(img_index));
}
}
}
}
return cv_img;
}
all code :
http://lab.deepaivision.com/2017/06/opencv-mat-caffe-datum-datum-mat.html
Addition to the answer by #ttagu99 , in the float section there is a slight bug:
The line:
ptr[img_index++] = static_cast<float>(datum.float_data(img_index));
Should be in fact:
int datum_index = (c * datum_height + h) * datum_width + w;
ptr[img_index++] = static_cast<float>(datum->float_data(datum_index));
This fixes the order of writing the data to the matrix. Otherwise, you only see lines of color.
Currently I am working with Faster RCNN using C++. I am trying to load cv Mat object (color image) to the net_->blob_by_name("data"). I follow the given instruction here https://github.com/YihangLou/FasterRCNN-Encapsulation-Cplusplus but the result is really bad:
I didn't change anything from the original code. So I suspect loading data to blob might be the issue.
Code:
float im_info[3];
float data_buf[height*width*3];
float *boxes = NULL;
float *pred = NULL;
float *pred_per_class = NULL;
float *sorted_pred_cls = NULL;
int *keep = NULL;
const float* bbox_delt;
const float* rois;
const float* pred_cls;
int num;
for (int h = 0; h < cv_img.rows; ++h )
{
for (int w = 0; w < cv_img.cols; ++w)
{
cv_new.at<cv::Vec3f>(cv::Point(w, h))[0] = float(cv_img.at<cv::Vec3b>(cv::Point(w, h))[0])-float(102.9801);
cv_new.at<cv::Vec3f>(cv::Point(w, h))[1] = float(cv_img.at<cv::Vec3b>(cv::Point(w, h))[1])-float(115.9465);
cv_new.at<cv::Vec3f>(cv::Point(w, h))[2] = float(cv_img.at<cv::Vec3b>(cv::Point(w, h))[2])-float(122.7717);
}
}
cv::resize(cv_new, cv_resized, cv::Size(width, height));
im_info[0] = cv_resized.rows;
im_info[1] = cv_resized.cols;
im_info[2] = img_scale;
for (int h = 0; h < height; ++h )
{
for (int w = 0; w < width; ++w)
{
data_buf[(0*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[0]);
data_buf[(1*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[1]);
data_buf[(2*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[2]);
}
}
net_->blob_by_name("data")->Reshape(1, 3, height, width);
net_->blob_by_name("data")->set_cpu_data(data_buf);
net_->blob_by_name("im_info")->set_cpu_data(im_info);
net_->ForwardFrom(0);
bbox_delt = net_->blob_by_name("bbox_pred")->cpu_data();
num = net_->blob_by_name("rois")->num();
Any advices ?
Can you please modify the code and check ...
cv::resize(cv_new, cv_resized, cv::Size(width, height));
im_info[0] = cv_resized.rows;
im_info[1] = cv_resized.cols;
im_info[2] = img_scale;
net_->blob_by_name("data")->Reshape(1, 3, height, width);
const shared_ptr<Blob<float> >& data_blob = net_->blob_by_name("data");
float* data_buf = data_blob->mutable_cpu_data();
for (int h = 0; h < height; ++h )
{
for (int w = 0; w < width; ++w)
{
data_buf[(0*height+h)*width+w] = float(cv_resized.at<cv::Vec3f> cv::Point(w, h))[0]);
data_buf[(1*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[1]);
data_buf[(2*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[2]);
}
}
net_->Forward();