store condition-matched pixels in vector

Hi people, I have been stuck with this for 2 weeks now. I am just not able to figure this out.
I would appreciate any help, because I am devastated.
I have a list of images with an object on a rotating table.
To get all the pixel coordinates of the edge of my object (after applying canny edge detection),
I scan the image from left to find the first pixel that is larger than 0 (means not black), then from the right.
I am going to store these edges' pixel coordinates into a vector, and write the image at the same time.

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// I have 3 problems now
//1. after playing with the code, i found that i didnt get the edges' coordinates,
// in fact, i am only getting the pixel coordinates that are near to the edges +  the 
//coordinates around rotating table
// can anybody guide me how should i do to get only the object's edges' pixel coordinates?
//2. I was going to make a little changes on some pixel coordinates, then rewrite an image, 
//but i got some assertion error that i dont have on another project i had.
//3. I am not even sure if I am storing the pixels right, because i have problem in displaying 
//them out. 
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "iostream"
#include <vector>
#include <direct.h>
#include <algorithm> // for copy
#include <iterator> // for ostream_iterator


using namespace cv;
using namespace std;

Mat pic, gray;
int rows, cols;

string path_in = "C:/Users/Dell/Desktop/";
string path_out = "C:/Users/Dell/Desktop/New Folder/";


int main(int argc, char** argv)
{
	vector<cv::String> fn;
	vector<cv::String> fo;
	glob(path_in + "*.jpg", fn, false);
	glob(path_out + "*.jpg", fo, false);

	size_t count = fn.size();
	for (size_t i = 1; i < 2; i++) //try for an image first, if works, then try for all images in folder
	{
		pic = imread(fn[i], CV_LOAD_IMAGE_COLOR);

		namedWindow("Before", 1);
		cv::imshow("Before", pic);

		cvtColor(pic, gray, CV_BGR2GRAY);

		cout << fn[i] << endl;
		cout << pic.rows << ", " << pic.cols << endl; //480, 640
		
		//int arry[][] = {};
		//myVec.reserve(dimension * dimension);
		std::vector<Point2d> myVec;
	
		for (int r = 0; r < gray.rows; r++) {
			for (int c = 0; c < gray.cols; c++) {
				
				if (gray.at<uchar>(r, c) > 0) { //!=black
				//if (gray.at<uchar>(r, c) == 0) { //if it's black,	
					
					//cout << r << ", " << c << endl;
					//cin >> arry[r][c];
					//gray.at<uchar>(r, c) = 255;
					myVec.push_back(Point2d(r, c));
					//cout << Point2d(r, c) << endl;
					
				continue;
				
				}
				break;
			}
		}

		
		for (size_t  k = gray.rows - 1 ; k != (size_t)-1; k--) {
			for (size_t  l = gray.cols - 1; l != (size_t)-1; l--) {

				if (gray.at<uchar>(k, l) > 0) { //!=black
				//if (gray.at<uchar>(k, l) == 0) { //if it's black, 
					//gray.at<uchar>(k, l) = 255;  //paint to white

					//that's how i found it didnt take the edges, but those coordinates near to edges
					//guess that , other than edges, some pixels are not black too
					myVec.push_back(Point2d(k, l));

					continue;

				}
				break;
			}
		}

		std::copy(myVec.begin(), myVec.end(), std::ostream_iterator<Point2d>(std::cout, " "));
		//no error, but it didnt cout my vector output

		imshow("After", gray);
		waitKey(0);
		imwrite(fo[i], gray); //Assertion error. not working:( no image saved in output folder

	}
	return 0;
}

	//waitKey(0) not working, 
	//http://blog.csdn.net/u010963435/article/details/78658397
Last edited on
It seems to me that your logic is backwards. Line 65 is storing every non-black point in the column. As soon as you hit a black point, you break out of the column loop. It sounds like you want to break out of both loops when you hit a non-black point.

Also, you're breaking out of the column loop, but not the row loop, so it will go through all rows.

Are you certain that you want pixels that are absolutely black? If these images come from a camera then it's likely that a few will be very dark, but not black. You might want to consider very dark pixels to be black too.

Here is what I think you want:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const int threshold = 3;   // or some other very small value.
for (int r = 0; r < gray.rows; r++) {
	int c;
	for (c = 0; c < gray.cols; c++) {
		if (gray.at<uchar>(r, c) > threshold) { // Pixel isn't really really dark
			myVec.push_back(Point2d(r, c));
			break;
		}
	}
	// If you found a non-black pixel then break out of the row loop.
	// If myVec was empty coming into the row loop then it would be easier
	// to change it's condition to r < gray.rows && myVec.size() == 0
	if (c < gray.cols) {
		break;
	}
}
Thank you so so much for your reply.
I apologize for my bad english as a non-native speaker.
I dont think i make myself clear in my question.
And guess my code is not close to what i am trying to achieve.

I am actually trying to store the first not-black pixel coordinates in each row (from the left and right) in my vector.
since i have 480 rows, i would think to get approximately... 480*2 entries in the vector.

Thanks for clarifying. If you want the first non-black pixel in each row then just delete lines 10-15 in my code. And you'll have to make similar changes to the second loop that looks for the first non-black pixel from the right.
May I just confirm with you that, is it true that

1. Threshold actually have values from 0-255?

2. Line5 in your code means, it stores the first pixel coordinate, when that particular coordinate has pixel value that is bigger than threshold?

3. I have learnt that .. not all of the pixel value of my object's edge are of the same value, also the code tells me that at most rows, the pixel coordinates value that im getting are near to the edge but not at the edge.. is there any other method i should go for the get the edge pixel coordinates?

by applying edge detection , i can clearly see my edge, im just having problem extracting their edge's pixel coordination.


thanks again
1. Threshold could be any value that can be returned from gray.at<uchar>(r, c). I don't know if that's limited to 0-255 or 0-0xffffffff, so you'll have to figure that out yourself. The point is that it should be some value that indicates that you're definitely out of the "black zone" of the image.

2. Correct.

3. That's the hard part isn't it? :) I haven't done much image processing so I don't know what techniques are best. You may need to examine the edges by hand to figure out what's the best thing to do. Do you need to experiment with the threshold value? Use a moving average to ensure you're really at the edge? Examine pixels around the edge to see if there's a better choice? I don't know, but I assume there are algorithms to do this.

Maybe someone else reading this can offer suggestions?
Ouch, there is no suggestion being offered.

Thank you dhayden for your answer. :)

At last, I went for threshold method to get binary image so that there is no "not so dark zone" in image.
Topic archived. No new replies allowed.