opencv remap function : How to set pixel value to (0,0,0) - opencv

Function call is:
remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) );
map_x and map_y defines as below:
for( int j = 0; j < src.rows; j++ )
{ for( int i = 0; i < src.cols; i++ ){
if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )
{
map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;
map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;
}
else{
map_x.at<float>(j,i) = 0 ;
map_y.at<float>(j,i) = 0 ;
}
}
}
You can see the original and resulting image. I want to ask:
How to set the outer parts of the result image(green part) to black(r=0,g=0,b=0)?

I think that you are mapping all pixels on the border to the original pixel at location (0,0). Try to replace the following
else {
map_x.at<float>(j,i) = 0 ;
map_y.at<float>(j,i) = 0 ;
}
by this
else {
map_x.at<float>(j,i) = -1 ;
map_y.at<float>(j,i) = -1 ;
}

Related

Is this the correct code for SAD(Sum of Absolute difference)? I am having trouble offsetting the larger matrix by required bits/pixels

//8x8 Array to perform operation on
//2x2 Array to perform operation
//used pointers
//SAD = sum(|a00-b00|+|a01-b01|+|a10-b10|+|a11-b11|)
//Then the 2x2 block should move towards the next 2x2 block on the 8x8 matrix and perform the same operation.
for ( x = 0; x < 2; x++ )
{
for ( y = 0; y < 2; y++ )
{
short sad = 0;
// loop through the template image
for ( j = 0; j < 8 ; j++ )
{
for ( i = 0; i < 8; i++ )
{
int p_SearchIMG = *( *(p + i + x) + (y + j));
printf("%i\t\n",p_SearchIMG);
int p_TemplateIMG = *( *(p1 + i) + j);
//printf("%i\t\n",p_TemplateIMG);
int temp = abs(p_SearchIMG - p_TemplateIMG);
//printf("temp[%d][%d] = %i\t\n",(i+x), (y+j), temp);
//if((i+x)==7 || (y+j)==7)
//break;
//short sad += temp;
//printf("%i\t\n",short);
}
}
}
}
//Having trouble to shift the 2X2 block.

Looking for an more efficient way to create a 4 directional linked-list

I am trying to create a method that will link all Cell objects set up in a 2D array named CellGrid[,]
My question is: Since most of the code in SetDirection() is so similar, it seem there is a better way to achieve my goal.
(Side note: This is functional but the execution feels "off" )
private void SetDirection()
{
int x = 0, y = 0;
for ( int i = 0 ; i < Size * (Size - 1);)//setting all UP pointers
{
if ( i == 0 ) { x = 0; y = 1;}//initial setup
for ( x = 0 ; x < Size ; x++ )
{
CellGrid[x,y].SetPointer(CellGrid[x,y-1] , Direction.Up );
i++;
}
y++;
}
for ( int i = 0 ; i < Size * (Size - 1);) //setting all DOWN pointers
{
if ( i == 0 ) { x = 0; y = 0;}//initial setup
for ( x = 0 ; x < Size ; x++ )
{
CellGrid[x,y].SetPointer(CellGrid[x,y+1], Direction.Down);
i++;
}
y++;
}
for ( int i = 0 ; i < Size * (Size - 1);)//setting all LEFT pointers
{
if ( i == 0 ) { x = 1; y = 0;}//initial setup
for ( y = 0 ; y < Size ; y++ )
{
CellGrid[x, y].SetPointer( CellGrid[x-1,y], Direction.Left);
i++;
}
x++;
}
for ( int i = 0 ; i < Size * (Size - 1);) //setting all RIGHT pointers
{
if ( i == 0 ) { x = 0; y = 0;}//initial setup
for ( y = 0 ; y < Size ; y++ )
{
CellGrid[x, y].SetPointer( CellGrid[x+1,y], Direction.Right);
i++;
}
x++;
}
}
public void SetPointer( Cell cellRef ,GridBuilder.Direction dir)
{
switch ( dir )
{
case GridBuilder.Direction.Up:
this.Up = cellRef;
break;
case GridBuilder.Direction.Down:
this.Down = cellRef;
break;
case GridBuilder.Direction.Left:
this.Left = cellRef;
break;
case GridBuilder.Direction.Right:
this.Right = cellRef;
break;
}
}
You can indeed use one set of loops to make the links in all four directions. This is based on two ideas:
When setting a link, immediately set the link in the opposite direction between the same two cells.
When setting a link, immediately set the link between the two cells that are located in the mirrored positions -- mirrored by the main diagonal (x <--> y).
private void SetDirection() {
for (int i = 1; i < Size; i++) {
for (int j = 0; j < Size; j++) {
CellGrid[i, j].SetPointer(CellGrid[i-1, j], Direction.Left);
CellGrid[i-1, j].SetPointer(CellGrid[i, j], Direction.Right);
CellGrid[j, i].SetPointer(CellGrid[j, i-1], Direction.Up);
CellGrid[j, i-1].SetPointer(CellGrid[j, i], Direction.Down);
}
}
}

OpenCV Error: Assertion failed, mat.hpp line 548

first I gave the following error in the code
int KK = 10;
int colors[KK];
then I wrote const int instead of kk and fixed the error
I'm using the opencv library but I'm getting an error somewhere. When i and j are 713 48, they do not give an error, but in the next cycle, i and j are 713 and 49, and they give an error code.(OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file c:\opencv\build\include\opencv2\core\mat.hpp, line 548)
the error gives in this row.
clustered.at(i,j) = (float)(colors[bestLabels.at(1,z)]);
I share the detailed code below
int KK = 10;
int colors[KK];
Mat p;
Mat bestLabels, centers;
vector<Mat> bgr, bgrBN;
split(frame_color, bgr);
Mat mask, clustered;
Mat clusteredAll = Mat::zeros(frame_color.rows, frame_color.cols, CV_32F);
for (int k = 0; k < contoursN.size(); k++)
{
mask = Mat::zeros(frame_color.rows, frame_color.cols, CV_8U);
drawContours(mask, contoursN, k, CV_RGB(255,255,255), CV_FILLED);
clustered = Mat::zeros(frame_color.rows, frame_color.cols, CV_32F);
int A = 0;
for (int i = 0; i < frame_color.rows; i++)
for (int j = 0; j < frame_color.cols; j++)
if (mask.at<uchar>(i,j) != 0)
A++;
if (A > 20)
{
p = Mat::zeros(A, G, CV_32F);
double moy = 0;
int z = 0;
for (int i = 0; i < frame_color.rows; i++)
{
for (int j = 0; j < frame_color.cols; j++)
{
if (mask.at<uchar>(i,j) != 0)
{
p.at<float>(z,0) = bgr[0].data[i*frame_color.cols+j] / 255.0;
p.at<float>(z,1) = bgr[1].data[i*frame_color.cols+j] / 255.0;
p.at<float>(z,2) = bgr[2].data[i*frame_color.cols+j] / 255.0;
z++;
moy = moy + frame.at<uchar>(i,j);
}
}
}
moy = moy/z;
double var = 0;
for (int i = 0; i < frame_color.rows; i++)
for (int j = 0; j < frame_color.cols; j++)
if (mask.at<uchar>(i,j) != 0)
var = var+(frame.at<uchar>(i,j) - moy)*(frame.at<uchar>(i,j) - moy);
var = var/(z*z);
int K = 1 + log(1+(A/A0)+(var/var0));
kmeans(p, K, bestLabels, TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0), 3, KMEANS_PP_CENTERS, centers);
for(int i=0; i<KK; i++)
colors[i] = 255/(i+1);
z = 0;
for (int i = 0; i < frame_color.rows; i++)
{
for (int j = 0; j < frame_color.cols; j++)
{
if (mask.at<uchar>(i,j) != 0)
{
clustered.at<float>(i,j) = (float)(colors[bestLabels.at<int>(1,z)]);
z++;
}
}
}
clusteredAll = clusteredAll + clustered;
clustered.convertTo(clustered, CV_8U);
}

Contour segmentation

I have a contour which consists of curved segments and straigth segments. Is there any possibility to segment the contour into the curved and straigth parts?
So this is an example for a contour
I would like to have a segmentation like this:
Do you have any idea how I could solve such a problem
Thank you very much and best regards
Yes I got the solution with the link #PSchn posted. I just go through the contour points and defined a border. Everything under the border is a "curved segment" everthing else is a straigth segment. Thank you for your help!!
vector<double> getCurvature(vector<Point> const& tContourPoints, int tStepSize)
{
int iplus;
int iminus;
double acurvature;
double adivisor;
Point2f pplus;
Point2f pminus;
// erste Ableitung
Point2f a1stDerivative;
// zweite Ableitung
Point2f a2ndDerivative;
vector< double > rVecCurvature( tContourPoints.size() );
if ((int)tContourPoints.size() < tStepSize)
{
return rVecCurvature;
}
for (int i = 0; i < (int)tContourPoints.size(); i++ )
{
const Point2f& pos = tContourPoints[i];
iminus = i-tStepSize;
iplus = i+tStepSize;
if(iminus < 0)
{
pminus = tContourPoints[iminus + tContourPoints.size()];
}
else
{
pminus = tContourPoints[iminus];
}
if(iplus > (int)tContourPoints.size())
{
pplus = tContourPoints[iplus - (int)tContourPoints.size()];
}
else
{
pplus = tContourPoints[iplus];
}
a1stDerivative.x = (pplus.x - pminus.x) / ( iplus-iminus);
a1stDerivative.y = (pplus.y - pminus.y) / ( iplus-iminus);
a2ndDerivative.x = (pplus.x - 2*pos.x + pminus.x) / ((iplus-iminus)/2*(iplus-iminus)/2);
a2ndDerivative.y = (pplus.y - 2*pos.y + pminus.y) / ((iplus-iminus)/2*(iplus-iminus)/2);
adivisor = a2ndDerivative.x*a2ndDerivative.x + a2ndDerivative.y*a2ndDerivative.y;
if ( abs(adivisor) > 10e-8 )
{
acurvature = abs(a2ndDerivative.y*a1stDerivative.x - a2ndDerivative.x*a1stDerivative.y) / pow(adivisor, 3.0/2.0 ) ;
}
else
{
acurvature = numeric_limits<double>::infinity();
}
rVecCurvature[i] = acurvature;
}
return rVecCurvature;
}
Once I get the curvature I defined a border and went through my contour:
acurvature = getCurvature(aContours_img[0], 50);
if(acurvature.size() > 0)
{
// aSegmentChange =1 --> curved segment
// aSegmentChange =0 --> straigth segment
if( acurvature[0] < aBorder)
{
aSegmentChange = 1;
}
else
{
aSegmentChange = 0;
}
// Kontur segmentieren
for(int i = 0; i < (int)acurvature.size(); i++)
{
aSegments[aSegmentIndex].push_back(aContours_img[0][i]);
aCurveIndex[aSegmentIndex].push_back(aSegmentChange);
if( acurvature[i] < aBorder && aSegmentChange == 0 )
{
aSegmentIndex++;
aSegmentChange = 1;
}
if( acurvature[i] > aBorder && aSegmentChange == 1 )
{
aSegmentIndex++;
aSegmentChange = 0;
}
if(aSegmentIndex >= (int)aSegments.size()-1)
{
aSegments.resize(aSegmentIndex+1);
aCurveIndex.resize(aSegmentIndex+1);
}
}
}
This is my contour
And this is the result of segmentation

Boxing Detected Objects in OpenCV

I am currently implementing a connected components algorithm and the last step of the algorithm requires me to enclose the objects I found in a box. I have attempted to enclose an object in a box and this is the result:
As you can see some of them seem to be enclosed in a box. Some of the lines of the box are not seen unless I stretch the windows of the imshow function's output and also some of them have color when I expected a line with a shade of gray.
My question is: Is the object really getting enclosed since I remember when I ran a similar code of mine into a different OS the lines with color are not see at all but are seen in my computer. Additionally, why are some of the lines in a different color given that I was expecting a shade of gray.
Mat src, src_gray;
Mat dst, detected_edges;
const char* window_name = "THRESHOLDED IMAGE";
/**
* #function connectedComponent
*/
static void connectedComponent(int, void*)
{
Mat test; //dummy
Mat sub;
int newObject = 0;
int zeroTest = 0, nonZero = 0;
int arr[5] = {0,0,0,0,0};
/// Reduce noise with a kernel 3x3
blur( src_gray,detected_edges, Size(3,3) ); //filtering out of noise
namedWindow("INITIAL", WINDOW_NORMAL);
imshow("INITIAL",detected_edges);
resizeWindow("INITIAL", 300, 300);
threshold(detected_edges, detected_edges, 0,255, THRESH_BINARY | THRESH_OTSU);
int** newSub = new int*[detected_edges.rows];
for(int i = 0; i < detected_edges.rows; i++)
newSub[i] = new int[detected_edges.cols];
for(int i = 0; i < detected_edges.rows; i++){
for(int j = 0; j < detected_edges.cols; j++){
newSub[i][j] = 0;
}
}
/*INITIAL MARKING LOOP*/
for(int i = 0; i < detected_edges.rows; i++){
for(int j = 0; j < detected_edges.cols; j++){
if(detected_edges.at<uchar>(i,j) == 0){
if(i-1 < 0 && j-1 < 0){
newObject = newObject + 1; //no values
newSub[i][j] = newObject;
}else if(i-1 >= 0 && j-1 < 0){
if(newSub[i-1][j] != 0){
newSub[i][j] = newSub[i-1][j]; //only up has value
}else{
newObject = newObject + 1; //no values
newSub[i][j] = newObject;
}
}else if(i-1 < 0 && j-1 >= 0){
if(newSub[i-1][j] != 0){
newSub[i][j] = newSub[i-1][j]; //only left has value
}else{
newObject = newObject + 1; //no values
newSub[i][j] = newObject;
}
}else{
if(newSub[i-1][j] == 0 && newSub[i][j-1] == 0){
newObject = newObject + 1; //no values
newSub[i][j] = newObject;
}else if(newSub[i-1][j] == newSub[i][j-1]){ //same value
newSub[i][j] = newSub[i-1][j];
}else if((newSub[i-1][j] != 0 && newSub[i][j-1] == 0)){
newSub[i][j] = newSub[i-1][j]; //only up has value
}else if(newSub[i-1][j] == 0 && newSub[i][j-1] != 0 ){
newSub[i][j] = newSub[i][j-1]; //only left has value
}else if(newSub[i-1][j] != newSub[i][j-1]){
newSub[i][j] = newSub[i-1][j]; //different values follow upper's value
}
}
}
}
}
int a = 1;
int maxRows = detected_edges.rows;
int maxCols = detected_edges.cols;
/*CONNECTING PIXELS RIGHT-BOTTOM*/
while(a < newObject){
int update = 0;
for(int i = 0; i < maxRows; i++){
for(int j = 0; j < maxCols; j++){
if(newSub[i][j] == a){
if(i+1 < maxRows && j+1 < maxCols){
if(newSub[i][j+1] > a){ //both points allowed
int value = newSub[i][j+1]; //get the value I need to replace
for(int h = 0; h < maxRows; h++){
for(int k = 0; k < maxCols; k++){
if(newSub[h][k] == value){ //replace all instances of that value
newSub[h][k] = a;
}
}
}
update = 1;
}
if(newSub[i+1][j] > a){ //both points allowed
int value = newSub[i+1][j]; //get the value I need to replace
for(int h = 0; h < maxRows; h++){
for(int k = 0; k < maxCols; k++){
if(newSub[h][k] == value){
newSub[h][k] = a; //replace all instances of that value
}
}
}
update = 1;
}
}else if(i+1 > maxRows && j+1 < maxCols){
if(newSub[i][j+1] > a){ //bottom is not allowed
int value = newSub[i][j+1]; //get the value I need to replace
for(int h = 0; h < maxRows; h++){
for(int k = 0; k < maxCols; k++){
if(newSub[h][k] == value){
newSub[h][k] = a; //replace all instances of that value
}
}
}
update = 1;
}
}else if(i+1 < maxRows && j+1 > maxCols){
if(newSub[i+1][j] > a){ //right is not allowed
int value = newSub[i+1][j]; //get the value I need to replace
for(int h = 0; h < maxRows; h++){
for(int k = 0; k < maxCols; k++){
if(newSub[h][k] == value){ //replace all instances of that value
newSub[h][k] = a;
}
}
}
update = 1;
}
}
}
}
}
a++;
}
/*CONNECTING PIXELS LEFT-TOP*/
a = newObject;
while(a > 0){
int update = 0;
for(int i = maxRows-1; i > 0; i--){
for(int j = maxCols-1; j > 0 ; j--){
if(newSub[i][j] == a){
if(i-1 >= 0 && j-1 >= 0){
if(newSub[i][j-1] > a){ //both points allowed
int value = newSub[i][j-1]; //get the value I need to replace
for(int h = 0; h < maxRows; h++){
for(int k = 0; k < maxCols; k++){
if(newSub[h][k] == value){
newSub[h][k] = a;
}
}
}
update = 1;
}
if(newSub[i-1][j] > a){
int value = newSub[i-1][j]; //get the value I need to replace
for(int h = 0; h < maxRows; h++){
for(int k = 0; k < maxCols; k++){
if(newSub[h][k] == value){ //replace all instances of that value
newSub[h][k] = a;
}
}
}
update = 1;
}
}else if(i-1 >= 0 && j-1 < 0){
if(newSub[i][j-1] > a){ //left is not allowed
int value = newSub[i][j-1]; //get the value I need to replace
for(int h = 0; h < maxRows; h++){
for(int k = 0; k < maxCols; k++){ //replace all instances of that value
if(newSub[h][k] == value){
newSub[h][k] = a;
}
}
}
update = 1;
}
}else if(i-1 < 0 && j-1 >= 0){
if(newSub[i-1][j] > a){ //top is not allowed
int value = newSub[i-1][j]; //get the value I need to replace
for(int h = 0; h < maxRows; h++){
for(int k = 0; k < maxCols; k++){ //replace all instances of that value
if(newSub[h][k] == value){
newSub[h][k] = a;
}
}
}
update = 1;
}
}
}
}
}
a--;
}
for(int i = 0; i < maxRows; i++){
for(int j = 0; j < maxCols; j++){
int check = 0;
if(newSub[i][j] != 0){
for(int k = 0; k < 5; k++){
if(newSub[i][j] == arr[k]){ //check if there is an instance of the value in the given array of values
check = 1;
break;
}
}
if(check == 0){
for(int r = 0; r < 5; r++){
if(arr[r] == 0){
arr[r] = newSub[i][j]; //if new value is found add to array
break;
}
}
}
}
}
}
/*
I HAVE AN ARRAY CONTAINING ALL VALUES
**/
src.copyTo( sub, detected_edges);
sub = Scalar::all(0);
/*SET AN INTENSITY FOR CORRESPONDING VALUES*/
int intensity = 50;
a = 0;
while(a < 5){
int update = 0;
for(int i = 0; i < maxRows; i++){
for(int j = 0; j < maxCols; j++){
if(newSub[i][j] == arr[a]){
sub.at<uchar>(i,j) = intensity;
}
}
}
a++;
intensity = intensity + 50;
}
a = 250;
/*GETTING MIN-MAX COORDINATES*/
while(a >= 50){
int setter = 0;
int minRow = 0;
int minCol = 0;
int maxRow = 0;
int maxCol = 0;
for(int i = 0; i < maxRows; i++){
for(int j = 0; j < maxCols; j++){
if(sub.at<uchar>(i,j) == a){
if(setter == 0){
minRow = i;
minCol = j;
maxRow = i;
maxCol = j;
setter = 1;
}else{
if(i <= minRow){
minRow = i;
}
else{
if(i > maxRow){
maxRow = i;
}
}
if(j <= minCol){
minCol = j;
}
else{
if(j > maxCol){
maxCol = j;
}
}
}
}
}
}
/*THIS IS WHERE I MAKE MY BOUNDING BOX*/
for(int i = minRow; i < maxRow; i++){
sub.at<uchar>(i,minCol) = 255; //set up the horizontal lines
sub.at<uchar>(i,maxCol) = 255;
}
for(int i = minCol; i < maxCol; i++){
sub.at<uchar>(minRow,i) = 255; //set up the vertical lines
sub.at<uchar>(maxRow,i) = 255;
}
a = a - 50;
}
dst = Scalar::all(0);
src.copyTo( dst, detected_edges);
imshow( window_name, dst );
namedWindow("FINAL", WINDOW_NORMAL);
imshow("FINAL",sub); //final output
resizeWindow("FINAL", 300, 300);
for(int i = 0; i < detected_edges.rows; i++)
delete[] newSub[i];
delete[] newSub;
}
/**
* #function main
*/
int main( int, char** argv )
{
/// Load an image
src = imread( argv[1] );
if( src.empty() )
{ return -1; }
/// Create a matrix of the same type and size as src (for dst)
dst.create( src.size(), src.type() );
/// Convert the image to grayscale
cvtColor( src, src_gray, COLOR_BGR2GRAY ); //grayscale for one channel for easy computation
/// Create a window
namedWindow( window_name, WINDOW_NORMAL );
resizeWindow(window_name, 300,300);
/// Show the image
connectedComponent(0, 0);
/// Wait until user exit program by pressing a key
waitKey(0);
return 0;
}

Resources