Region Growing OpenCv c/c++ with onMouse - c++

I am encountering an issue with my code. I aim to generate three seeds at different locations in the image and observe the pixels growing. I am using the onMouse function to select the areas, however, only the last point is being recognized. What changes do I need to make for this code to function correctly?
Pont seed,seed2,seed3;
bool clicked = false;
void onmouse(int event, int x, int y, int flags, void* userdata)
{
if (event == EVENT_LBUTTONDOWN) {
seed = Point2i(y, x);
seed2 = Point2i(y, x);
seed3 = Point2i(y, x);
clicked = true;
}
}
int main() {
string path = "C:/img_4.jpg";
Mat im_gray = imread(path, IMREAD_GRAYSCALE);
Mat im_new;
int threshold = 50;
imshow("Image", im_gray);
setMouseCallback("Image", onmouse, NULL);
while (!clicked) {
waitKey(0);
}
regionGrowing_teste1(im_gray, im_new, seed, seed2, seed3, threshold);
imshow("Segmented", im_new);
waitKey(0);
return 0;
}
Mat regionGrowing_teste1(Mat& src, Mat& dst, Point2i seed1, Point2i seed2, Point2i seed3, int threshold) {
dst = Mat::zeros(src.rows, src.cols, CV_8UC1);
vector<Point2i> queue1, queue2, queue3;
queue1.push_back(seed1);
queue2.push_back(seed2);
queue3.push_back(seed3);
int intensity1 = (int)src.at<uchar>(seed1);
int intensity2 = (int)src.at<uchar>(seed2);
int intensity3 = (int)src.at<uchar>(seed3);
int x, y;
while (!queue1.empty() || !queue2.empty() || !queue3.empty()) {
if (!queue1.empty()) {
Point2i p = queue1.back();
queue1.pop_back();
x = p.x; y = p.y;
if (x > 0 && x < src.rows - 1 && y > 0 && y < src.cols - 1) {
if ((int)dst.at<uchar>(x, y) == 0) {
int intensityNeighbor = (int)src.at<uchar>(x, y);
if (abs(intensity1 - intensityNeighbor) < threshold) {
dst.at<uchar>(x, y) = 255;
queue1.push_back(Point2i(x + 1, y));
queue1.push_back(Point2i(x - 1, y));
queue1.push_back(Point2i(x, y + 1));
queue1.push_back(Point2i(x, y - 1));
}
}
}
}
if (!queue2.empty()) {
Point2i p = queue2.back();
queue2.pop_back();
x = p.x; y = p.y;
if (x > 0 && x < src.rows - 1 && y > 0 && y < src.cols - 1) {
if ((int)dst.at<uchar>(x, y) == 0) {
int intensityNeighbor = (int)src.at<uchar>(x, y);
if (abs(intensity2 - intensityNeighbor) < threshold) {
dst.at<uchar>(x, y) = 255;
queue2.push_back(Point2i(x + 1, y));
queue2.push_back(Point2i(x - 1, y));
queue2.push_back(Point2i(x, y + 1));
queue2.push_back(Point2i(x, y - 1));
}
}
}
}
// process points in queue3
if (!queue3.empty()) {
Point2i p = queue3.back();
queue3.pop_back();
x = p.x; y = p.y;
if (x > 0 && x < src.rows - 1 && y > 0 && y < src.cols - 1) {
if ((int)dst.at<uchar>(x, y) == 0) {
int intensityNeighbor = (int)src.at<uchar>(x, y);
if (abs(intensity3 - intensityNeighbor) < threshold) {
dst.at<uchar>(x, y) = 255;
queue3.push_back(Point2i(x + 1, y));
queue3.push_back(Point2i(x - 1, y));
queue3.push_back(Point2i(x, y + 1));
queue3.push_back(Point2i(x, y - 1));
}
}
}
}
}
for (int i = 0; i < src.rows; i++) {
for (int j = 0; j < src.cols; j++) {
if (dst.at<uchar>(i, j) == 0) {
dst.at<uchar>(i, j) = src.at<uchar>(i, j);
}
}
}
return dst;
}
I hope to see the placement of three points and watch them grow.

Related

Region Growing for Cr and Cb (YCbCr) components

I want to implement region growing algorithm for components Cr and Cb (YCbCr) (separate and combined) with manually chosen seed point (mouse click).
At the moment I have two functions that implement region growing for the H component in the HSV color space.
bool isOk(int new_x, int new_y, int width, int height)
{
if (new_x < 0 || new_y < 0 || new_x >= width || new_y >= height)
return false;
return true;
}
void lab04_MouseCallback(int event, int x, int y, int flags, void* param)
{
Mat* src = (Mat*)param;
int height = (*src).rows;
int width = (*src).cols;
if (event == CV_EVENT_LBUTTONDOWN)
{
printf("Seed point(x,y): %d,%d\n", x, y);
Mat labels = Mat::zeros((*src).size(), CV_16UC1);
int w = 3,
hue_avg = 0,
inf_x, sup_x,
inf_y, sup_y,
cnt = 0;
inf_x = (x - w < 0) ? 0 : x - w;
inf_y = (y - w < 0) ? 0 : y - w;
sup_x = (x + w >= width) ? (width - 1) : x + w;
sup_y = (y + w >= height) ? (height - 1) : y + w;
printf("inf x: %d sup x: %d --- inf y: %d sup y: %d\n", inf_x, sup_x, inf_y, sup_y);
for (int i = inf_y; i <= sup_y; ++i)
{
for (int j = inf_x; j <= sup_x; ++j)
{
hue_avg += (*src).data[i * width + j];
//printf("H at <%d, %d> is %d\n", i, j, (*src).data[i * width + j]);
}
}
hue_avg /= (sup_x - inf_x + 1) * (sup_y - inf_y + 1);
printf("Hue average: %d\n\n", hue_avg);
int k = 1, N = 1, hue_std = 10;
int konst = 3;
int T = konst * (float)hue_std;
queue<Point> Q;
Q.push(Point(x, y));
while (!Q.empty())
{
int dx[8] = { -1, 0, 1, 1, 1, 0, -1, -1 };
int dy[8] = { -1, -1, -1, 0, 1, 1, 1, 0 };
Point temp = Q.front();
Q.pop();
for (int dir = 0; dir < 8; ++dir)
{
int new_x = temp.x + dx[dir];
int new_y = temp.y + dy[dir];
if (isOk(new_x, new_y, width, height))
{
//printf("(%d, %d)\n", new_x, new_y);
if (labels.at<ushort>(new_y, new_x) == 0)
{
//printf("labels(%d, %d) = %hu\n", new_x, new_y, labels.at<ushort>(new_y, new_x));
if (abs((*src).at<uchar>(new_y, new_x) - hue_avg) < T)
{
//printf("this one\n");
Q.push(Point(new_x, new_y));
labels.at<ushort>(new_y, new_x) = k;
hue_avg = ((N * hue_avg) + (*src).at<uchar>(new_y, new_x)) / (N + 1);
++N;
}
}
}
}
}
Mat dst = (*src).clone();
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (labels.at<ushort>(i, j) == 1)
{
dst.at<uchar>(i, j) = 255;
}
else
{
dst.at<uchar>(i, j) = 0;
}
}
}
imshow("dst", dst);
}
}
void lab04_MouseClick()
{
Mat src;
Mat hsv;
// Read image from file
char fname[MAX_PATH];
while (openFileDlg(fname))
{
src = imread(fname);
int height = src.rows;
int width = src.cols;
//Create a window
namedWindow("My Window", 1);
// Aplicare FTJ gaussian pt. eliminare zgomote: essential sa il aplicati
GaussianBlur(src, src, Size(5, 5), 0, 0);
// Componenta de culoare Hue a modelului HSV
Mat H = Mat(height, width, CV_8UC1);
// definire pointeri la matricea (8 biti/pixeli) folosita la stocarea
// componentei individuale H
uchar* lpH = H.data;
cvtColor(src, hsv, CV_BGR2HSV); // conversie RGB -> HSV
// definire pointer la matricea (24 biti/pixeli) a imaginii HSV
uchar* hsvDataPtr = hsv.data;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
// index in matricea hsv (24 biti/pixel)
int hi = i * width * 3 + j * 3;
int gi = i * width + j; // index in matricea H (8 biti/pixel)
lpH[gi] = hsvDataPtr[hi] * 510 / 360; // lpH = 0 .. 255
}
}
//set the callback function for any mouse event
setMouseCallback("My Window", lab04_MouseCallback, &H);
//show the image
imshow("My Window", src);
// Wait until user press some key
waitKey(0);
}
}
How can I change this code to be for components Cr and Cb?

Implementation of Harris Corner Detector using Sobel and Gaussian Blur in C++

I want to implement the harris corner detector. I found this page to be very helpful, since it shows how the detector is implemented using the basic opencv functions (like gaussianBlur and Sobel):
https://compvisionlab.wordpress.com/2013/03/02/harris-interest-point-detection-implementation-opencv/
Now I even want to implement Gaussian Blur and Sobel. If I run my Gaussian or Sobel over some Images it works but in combination with my Corner Detector it does not work. Can anybody help me please. The full Code is below, thx.
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
/// Global variables
Mat src, src_gray, dst;
int thresh = 200;
int max_thresh = 255;
char* source_window = "Source Image";
char* corners_window = "Corner Image";
/// Function header
void cornerHarris_demo(int, void*);
void cornerHarrisMe(int, int, double);
int xGradient(Mat, int, int);
int yGradient(Mat, int, int);
void SobelMe(Mat&,Mat&,int,int);
int borderCheck(int M, int x);
void SepGaussian(Mat&, Mat&, int, int);
/** #function main */
int main(int argc, char** argv)
{
/// Load source image and convert it to gray
src = imread("data/a-real-big-church.jpg", 1);
//Mat src_gray(src.size(), CV_8UC1);
cvtColor(src, src_gray, CV_BGR2GRAY);
/// Create a window and a trackbar
namedWindow(source_window, CV_WINDOW_AUTOSIZE);
createTrackbar("Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo);
imshow(source_window, src);
cornerHarris_demo(0, 0);
waitKey(0);
return(0);
}
/** #function cornerHarris_demo */
void cornerHarris_demo(int, void*)
{
Mat dst_norm, dst_norm_scaled;
/// Detector parameters
int blockSize = 2;
int apertureSize = 3;
double k = 0.04;
/// Detecting corners
cornerHarrisMe(blockSize, apertureSize, k);
/// Normalizing
normalize(dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
convertScaleAbs(dst_norm, dst_norm_scaled);
/// Drawing a circle around corners
for (int j = 0; j < dst_norm.rows; j++)
{
for (int i = 0; i < dst_norm.cols; i++)
{
if ((int)dst_norm.at<float>(j, i) > thresh)
{
circle(dst_norm_scaled, Point(i, j), 5, Scalar(255), 2, 8, 0);
}
}
}
/// Showing the result
namedWindow(corners_window, CV_WINDOW_AUTOSIZE);
imshow(corners_window, dst_norm_scaled);
}
void cornerHarrisMe(int blockSize, int apertureSize, double k)
{
Mat x2y2, xy, mtrace, x_der, y_der, x2_der, y2_der, xy_der, x2g_der, y2g_der, xyg_der;
//1: calculate x and y derivative of image via Sobel
SobelMe(src_gray, x_der, 1, 0);
SobelMe(src_gray, y_der, 0, 1);
//2: calculate other three images in M
pow(x_der, blockSize, x2_der);
pow(y_der, blockSize, y2_der);
multiply(x_der, y_der, xy_der);
//3: gaussain
SepGaussian(x2_der, x2g_der, 1, 0);
SepGaussian(y2_der, y2g_der, 0, 1);
SepGaussian(xy_der, xyg_der, 1, 1);
//4. calculating R with k
multiply(x2g_der, y2g_der, x2y2);
multiply(xyg_der, xyg_der, xy);
pow((x2g_der + y2g_der), blockSize, mtrace);
dst = (x2y2 - xy) - k * mtrace;
}
// gradient in the x direction
int xGradient(Mat image, int x, int y)
{
return image.at<uchar>(y - 1, x - 1) +
2 * image.at<uchar>(y, x - 1) +
image.at<uchar>(y + 1, x - 1) -
image.at<uchar>(y - 1, x + 1) -
2 * image.at<uchar>(y, x + 1) -
image.at<uchar>(y + 1, x + 1);
}
// gradient in the y direction
int yGradient(Mat image, int x, int y)
{
return image.at<uchar>(y - 1, x - 1) +
2 * image.at<uchar>(y - 1, x) +
image.at<uchar>(y - 1, x + 1) -
image.at<uchar>(y + 1, x - 1) -
2 * image.at<uchar>(y + 1, x) -
image.at<uchar>(y + 1, x + 1);
}
void SobelMe(Mat& source, Mat& destination, int xOrder, int yOrder){
int gradX, gradY, sum;
destination = source.clone();
if (xOrder == 1 && yOrder == 0){
for (int y = 1; y < source.rows - 1; y++){
for (int x = 1; x < source.cols - 1; x++){
gradX = xGradient(source, x, y);
sum = abs(gradX);
sum = sum > 255 ? 255 : sum;
sum = sum < 0 ? 0 : sum;
destination.at<uchar>(y, x) = sum;
}
}
}
else if (xOrder == 0 && yOrder == 1){
for (int y = 1; y < source.rows - 1; y++){
for (int x = 1; x < source.cols - 1; x++){
gradY = yGradient(source, x, y);
sum = abs(gradY);
sum = sum > 255 ? 255 : sum;
sum = sum < 0 ? 0 : sum;
destination.at<uchar>(y, x) = sum;
}
}
}
else if (xOrder == 1 && yOrder == 1)
for (int y = 1; y < source.rows - 1; y++){
for (int x = 1; x < source.cols - 1; x++){
gradX = xGradient(source, x, y);
gradY = yGradient(source, x, y);
sum = abs(gradX) + abs(gradY);
sum = sum > 255 ? 255 : sum;
sum = sum < 0 ? 0 : sum;
destination.at<uchar>(y, x) = sum;
}
}
}
int borderCheck(int M, int x){
if (x < 0)
return -x - 1;
if (x >= M)
return 2 * M - x - 1;
return x;
}
void SepGaussian(Mat& source, Mat& desination, int sigmaX, int sigmaY){
// coefficients of 1D gaussian kernel with sigma = 1
double coeffs[] = { 0.0545, 0.2442, 0.4026, 0.2442, 0.0545 };
Mat tempX, tempY;
float sum, x1, y1;
desination = source.clone();
tempY = source.clone();
tempX = source.clone();
// along y - direction
if (sigmaX == 0 && sigmaY == 1){
for (int y = 0; y < source.rows; y++){
for (int x = 0; x < source.cols; x++){
sum = 0.0;
for (int i = -2; i <= 2; i++){
y1 = borderCheck(source.rows, y - i);
sum = sum + coeffs[i + 2] * source.at<uchar>(y1, x);
}
desination.at<uchar>(y, x) = sum;
}
}
}
// along x - direction
else if (sigmaX == 1 && sigmaY == 0){
for (int y = 0; y < source.rows; y++){
for (int x = 0; x < source.cols; x++){
sum = 0.0;
for (int i = -2; i <= 2; i++){
x1 = borderCheck(source.cols, x - i);
sum = sum + coeffs[i + 2] * source.at<uchar>(y, x1);
}
desination.at<uchar>(y, x) = sum;
}
}
}
// along xy - direction
else if (sigmaX == 1 && sigmaY == 1){
for (int y = 0; y < source.rows; y++){
for (int x = 0; x < source.cols; x++){
sum = 0.0;
for (int i = -2; i <= 2; i++){
y1 = borderCheck(source.rows, y - i);
sum = sum + coeffs[i + 2] * source.at<uchar>(y1, x);
}
tempY.at<uchar>(y, x) = sum;
}
}
for (int y = 0; y < source.rows; y++){
for (int x = 0; x < source.cols; x++){
sum = 0.0;
for (int i = -2; i <= 2; i++){
x1 = borderCheck(source.cols, x - i);
sum = sum + coeffs[i + 2] * tempY.at<uchar>(y, x1);
}
desination.at<uchar>(y, x) = sum;
}
}
}
}
The Result:
Here is the a picture of the Result.
The Result is now the other way around, it detects areas where are no Corners.
In case there are some questions, feel free to ask me.

Connected Component labeling in OpenCV using recursive algorithm

I'm trying to implement connected component labeling in OpenCV using recursive algorithm. I'm not sure what I have implemented wrongly. the algorithm is like this
B is Binary Image, LB is Labelled Binary Image
procedure connected_component(B,LB)
{
LB:=negate(B);
label:=0;
findComponents(LB,label);
display(LB);
}
procedure findComponents(LB,label)
{
for L:=0 to maxRow
for P:= 0 to maxCol
if LB[L,P] == -1 then
{
label:=label+1;
search(LB,label,L,P);
}
}
procedure search(LB,label,L,P)
{
LB[L,P]:=label;;
Nset:= neighbours(L,P);
for each(L',P') in Nset
{
if(LB[L',P'] == -1) then
search(LB,label,L',P');
}
}
I have written the code in OpenCV as follows
#include<iostream>
#include<opencv2\opencv.hpp>
using namespace cv;
using namespace std;
void findComponents(Mat res, int label);
void search(Mat res, int label, int row, int col);
int main()
{
Mat src = imread("D:/My Library/test/peppers.bmp",0);
src.convertTo(src,CV_8S);
Mat th = src.clone();
threshold(src,th,128,255,CV_8S);
Mat res = th.clone();
for(int i=0;i<res.rows;i++)
for(int j=0;j<res.cols;j++)
res.at<signed char>(i,j) = 0 - th.at<signed char>(i,j);
int label = 0;
findComponents(res,label);
waitKey(0);
return 0;
}
void findComponents(Mat res, int label)
{
for (int i = 1; i < res.rows - 1; i++)
{
for (int j = 1; j < res.cols - 1; j++)
{
if (res.at<signed char>(i, j) == -255)
{
label++;
search(res, label, i, j);
}
}
}
imshow("CC Image", res);
}
void search(Mat res, int label, int row, int col)
{
res.at<signed char>(row, col) = label;
if (res.at<signed char>(row, col + 1) == -255) search(res, label, row, col + 1);
if (res.at<signed char>(row + 1, col + 1) == -255) search(res, label, row+1, col + 1);
if (res.at<signed char>(row + 1, col) == -255) search(res, label, row + 1, col);
if (res.at<signed char>(row + 1, col - 1) == -255) search(res, label, row + 1, col - 1);
else return;
}
The code is does not works. What have I made wrong in implementing the algorithm? I'm new to OpenCV.
You have a few problems in your code. The most important is that you shouldn't use CV_8S matrices. Why?
They have values limited in range [-128, 127]
checking for values equal to -255 won't work correctly
you are limited to at most 127 connected components per image
threshold won't work as expected
maybe others...
I re-implemented your code to correct for these issues:
you should use CV_32S for your labels.
you should account for borders
you can use Mat_<Tp> for easy access, instead of .at<Tp>
Below is the code. I used applyCustomColorMap to better visualize results.
#include <opencv2/opencv.hpp>
#include <algorithm>
#include <vector>
#include <stack>
using namespace cv;
void search(Mat1i& LB, int label, int r, int c)
{
LB(r, c) = label;
// 4 connected
if ((r - 1 > 0) && LB(r - 1, c) == -1) { search(LB, label, r - 1, c ); }
if ((r + 1 < LB.rows) && LB(r + 1, c) == -1) { search(LB, label, r + 1, c ); }
if ((c - 1 > 0) && LB(r, c - 1) == -1) { search(LB, label, r , c - 1); }
if ((c + 1 < LB.cols) && LB(r, c + 1) == -1) { search(LB, label, r , c + 1); }
// 8 connected
if ((r - 1 > 0) && (c - 1 > 0) && LB(r - 1, c - 1) == -1) { search(LB, label, r - 1, c - 1); }
if ((r - 1 > 0) && (c + 1 < LB.cols) && LB(r - 1, c + 1) == -1) { search(LB, label, r - 1, c + 1); }
if ((r + 1 < LB.rows) && (c - 1 > 0) && LB(r + 1, c - 1) == -1) { search(LB, label, r + 1, c - 1); }
if ((r + 1 < LB.rows) && (c + 1 < LB.cols) && LB(r + 1, c + 1) == -1) { search(LB, label, r + 1, c + 1); }
}
int findComponents(Mat1i& LB)
{
int label = 0;
for (int r = 0; r < LB.rows; ++r) {
for (int c = 0; c < LB.cols; ++c) {
if (LB(r, c) == -1) {
++label;
search(LB, label, r, c);
}
}
}
return label;
}
int connected_components(const Mat1b& B, Mat1i& LB)
{
// Foreground is > 0
// Background is 0
LB = Mat1i(B.rows, B.cols, 0);
LB.setTo(-1, B > 0);
// Foreground labels are initialized to -1
// Background labels are initialized to 0
return findComponents(LB);
}
void applyCustomColormap(const Mat1i& src, Mat3b& dst);
int main()
{
// Load grayscale image
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Binarize the image
Mat1b bin;
threshold(img, bin, 127, 255, THRESH_BINARY);
// Find labels
Mat1i labels;
int n_labels = connected_components(bin, labels);
// Show results
Mat3b out;
applyCustomColormap(labels, out);
imshow("Labels", out);
waitKey();
return 0;
}
void applyCustomColormap(const Mat1i& src, Mat3b& dst)
{
// Create JET colormap
double m;
minMaxLoc(src, nullptr, &m);
m++;
int n = ceil(m / 4);
Mat1d u(n * 3 - 1, 1, double(1.0));
for (int i = 1; i <= n; ++i) {
u(i - 1) = double(i) / n;
u((n * 3 - 1) - i) = double(i) / n;
}
std::vector<double> g(n * 3 - 1, 1);
std::vector<double> r(n * 3 - 1, 1);
std::vector<double> b(n * 3 - 1, 1);
for (int i = 0; i < g.size(); ++i)
{
g[i] = ceil(double(n) / 2) - (int(m) % 4 == 1 ? 1 : 0) + i + 1;
r[i] = g[i] + n;
b[i] = g[i] - n;
}
g.erase(std::remove_if(g.begin(), g.end(), [m](double v){ return v > m; }), g.end());
r.erase(std::remove_if(r.begin(), r.end(), [m](double v){ return v > m; }), r.end());
b.erase(std::remove_if(b.begin(), b.end(), [](double v){ return v < 1.0; }), b.end());
Mat1d cmap(m, 3, double(0.0));
for (int i = 0; i < r.size(); ++i) { cmap(int(r[i]) - 1, 0) = u(i); }
for (int i = 0; i < g.size(); ++i) { cmap(int(g[i]) - 1, 1) = u(i); }
for (int i = 0; i < b.size(); ++i) { cmap(int(b[i]) - 1, 2) = u(u.rows - b.size() + i); }
Mat3d cmap3 = cmap.reshape(3);
Mat3b colormap;
cmap3.convertTo(colormap, CV_8U, 255.0);
// Apply color mapping
dst = Mat3b(src.rows, src.cols, Vec3b(0, 0, 0));
for (int r = 0; r < src.rows; ++r)
{
for (int c = 0; c < src.cols; ++c)
{
dst(r, c) = colormap(src(r, c));
}
}
}
Please take care that a recursive implementation is not a good idea for labeling:
it's quite slow
it may fail if you go too deep with recursion, i.e. your components are very big
I suggest to use another algorithm. Here is an implementation of (almost) your algorithm in iterative form. I strongly recommend this one over yours. It can be trivially modified to output the points for each connected component as vector<vector<Point>>, just like cv::findContours would do:
int connected_components2(const Mat1b& img, Mat1i& labels)
{
Mat1b src = img > 0;
labels = Mat1i(img.rows, img.cols, 0);
int label = 0;
int w = src.cols;
int h = src.rows;
int i;
cv::Point point;
for (int y = 0; y<h; y++)
{
for (int x = 0; x<w; x++)
{
if ((src(y, x)) > 0) // Seed found
{
std::stack<int, std::vector<int>> stack2;
i = x + y*w;
stack2.push(i);
// Current component
std::vector<cv::Point> comp;
while (!stack2.empty())
{
i = stack2.top();
stack2.pop();
int x2 = i%w;
int y2 = i / w;
src(y2, x2) = 0;
point.x = x2;
point.y = y2;
comp.push_back(point);
// 4 connected
if (x2 > 0 && (src(y2, x2 - 1) != 0))
{
stack2.push(i - 1);
src(y2, x2 - 1) = 0;
}
if (y2 > 0 && (src(y2 - 1, x2) != 0))
{
stack2.push(i - w);
src(y2 - 1, x2) = 0;
}
if (y2 < h - 1 && (src(y2 + 1, x2) != 0))
{
stack2.push(i + w);
src(y2 + 1, x2) = 0;
}
if (x2 < w - 1 && (src(y2, x2 + 1) != 0))
{
stack2.push(i + 1);
src(y2, x2 + 1) = 0;
}
// 8 connected
if (x2 > 0 && y2 > 0 && (src(y2 - 1, x2 - 1) != 0))
{
stack2.push(i - w - 1);
src(y2 - 1, x2 - 1) = 0;
}
if (x2 > 0 && y2 < h - 1 && (src(y2 + 1, x2 - 1) != 0))
{
stack2.push(i + w - 1);
src(y2 + 1, x2 - 1) = 0;
}
if (x2 < w - 1 && y2>0 && (src(y2 - 1, x2 + 1) != 0))
{
stack2.push(i - w + 1);
src(y2 - 1, x2 + 1) = 0;
}
if (x2 < w - 1 && y2 < h - 1 && (src(y2 + 1, x2 + 1) != 0))
{
stack2.push(i + w + 1);
src(y2 + 1, x2 + 1) = 0;
}
}
++label;
for (int k = 0; k <comp.size(); ++k)
{
labels(comp[k]) = label;
}
}
}
}
return label;
}

Unhandled exception. Access violation reading location

I'm currently writing a BLOB detection algorithm. When I run it I get the error
Unhandled exception at 0x00007FF70476CDA7 in blobdetector.exe: 0xC0000005:
Access violation reading location 0x0000007BDDA0347D.
This is the part of the code where it breaks.
The debugger stops at the last line before the if(val == 255)
void connectivity(BlobBurnMat temp, size_t y, size_t x){
uchar* ptr = (uchar*)temp.getTemp().data;
size_t min_y = temp.getTemp().rows, min_x = temp.getTemp().cols, max_y = 0, max_x = 0;
for (int i = 0; i < 4; i++){
int kernel[4][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
int temp_y = y + kernel[i][0];
int temp_x = x + kernel[i][1];
uchar val = ptr[temp.getTemp().step * temp_y + temp_x]; //breaks here
if (val == 255) {
temp.setValZero(x, y);
x = temp_x;
y = temp_y;
if (temp_x > max_x)
max_x = temp_x;
if(temp_x < min_x)
min_x = temp_x;
if (temp_y > max_y)
max_y = temp_y;
if (temp_y < min_y)
min_y = temp_y;
int pass_x = ((max_x - min_x) / 2);
int pass_y((max_y - min_y) / 2);
setCoordinates(pass_x, pass_y);
connectivity(temp, y, x);
}
}
}
Here is the rest of the code. The above connectivity() method is in the BLOB class.
#include "opencv2/opencv.hpp"
#include<stdio.h>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;
class BlobBurnMat{
//Class used to store a copy of the source image where pixels get burned in BLOB finding.
private:
Mat temp;
public:
void initiate(Mat temp){
this -> temp = temp;
}
Mat getTemp(){
return temp;
}
void setValZero(int x, int y){
temp.at<uchar>(y, x) = 0;
}
};
class BLOB{
//BLOB class to store coordinates of the BLOBs before they are added to the vector-array-list-thingamajig
private:
int x, y;
public:
void setCoordinates(int x, int y){
this->x = x;
this->y = y;
}
int getX(){
return x;
}
int getY(){
return y;
}
void connectivity(BlobBurnMat temp){
connectivity(temp, x, y);
}
void connectivity(BlobBurnMat temp, int y, int x){
uchar* ptr = (uchar*)temp.getTemp().data;
int min_y = temp.getTemp().rows, min_x = temp.getTemp().cols, max_y = 0, max_x = 0;
for (int i = 0; i < 4; i++){
int kernel[4][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
int temp_y = y + kernel[i][0];
int temp_x = x + kernel[i][1];
uchar val = ptr[temp.getTemp().step * temp_y + temp_x];
if (val == 255) {
temp.setValZero(x, y);
x = temp_x;
y = temp_y;
if (temp_x > max_x)
max_x = temp_x;
if(temp_x < min_x)
min_x = temp_x;
if (temp_y > max_y)
max_y = temp_y;
if (temp_y < min_y)
min_y = temp_y;
int pass_x = ((max_x - min_x) / 2);
int pass_y((max_y - min_y) / 2);
setCoordinates(pass_x, pass_y);
connectivity(temp, y, x);
}
}
}
};
vector<Point2i> getBlobCoordinates(Mat src){
BlobBurnMat *temp = new BlobBurnMat();
temp->initiate(src.clone());
vector<Point2i> blobCoordinates; //Vector holding all BLOB coordinates
Point2i blobCoords; //Coordinates of a single BLOB
//Go through the binary matrix looking for white pixels.
for (size_t y = 0; y < src.rows; y++) {
for (size_t x = 0; x < src.cols; x++) {
uchar* ptr = (uchar*)temp->getTemp().data;
uchar val = ptr[temp->getTemp().step * y + x];
if (val == 255){
BLOB *blob = new BLOB();
blob->setCoordinates(x, y);
blob->connectivity(*temp);
blobCoords.x = blob->getX();
blobCoords.y = blob->getY();
blobCoordinates.push_back(blobCoords); //add a new element to the vector.
}
}
}
return blobCoordinates;
}
int main(int, char){
Mat src;
String path = "C:/Users/Runagar/Desktop/segment.jpg";
src = imread(path, 0);
if (src.data && !src.empty()){
imshow("blobie", src);
}
else cout << "You fucked up ";
vector <Point2i> blobCoordinates = getBlobCoordinates(src);
for (int k = 0; k < blobCoordinates.size(); k++)
cout << blobCoordinates[k];
waitKey(0);
return 0;
}
Thanks in advance!
When i == 2 and x == 0, temp_x == -1 so you read 1 byte before ptr outside the memory allocaded.
You have to handle the case when x == 0, y == 0, x == src.cols and y == src.rows.
Mat getTemp() returns a copy of your Mat instance.
uchar* ptr = (uchar*)temp.getTemp().data; retrieves a pointer from a temporary Mat instance. This instance is then immediately deleted, and you're left with a pointer to (presumably) properly deleted data.
Try Mat & getTemp() instead.

Seeded region growing with opencv

I need to select a pixel value and apply the region growing in terms of the seed pixel. After trying to write the code, the result was always a black image
regardless of what seed point I used. The whole problem is involved in the GrowColor function. My guess is a logical error with the ifs.
#include <cv.h>
#include <highgui.h>
using namespace std;
int xDim, yDim, zDim;
float ThreshHold = 45.0;
unsigned long total[3];
int coont, tt;
IplImage *Image1;
IplImage *Image2;
CvScalar s = cvScalar(0, 0, 0, 0);
CvScalar s11 = cvScalar(0, 0, 0, 0);
int Diff, mean[3], temp[3];
void GrowColor(int x, int y);
int main(int argc, char *argv[]) {
char value[4];
int pixType, dimCut;
int Dbug = false;
int Xseed = 40, Yseed = 234;
int i = 0, x, y;
Image1 = cvLoadImage("lenah.jpg");
yDim = Image1->height;
xDim = Image1->width;
// int step= Image1->widthStep;
//uchar* data = (uchar *)Image1->imageData;
//New image
Image2 = cvCreateImage(cvSize(Image1->width, Image1->height), IPL_DEPTH_8U,
1);
cvZero(Image2);
total[0] = total[1] = total[2] = coont = 0;
//Process
for (y = Yseed - 5; y <= Yseed + 5; y++)
for (x = Xseed - 5; x <= Xseed + 5; x++)
if ((x > 0) && (y > 0) && (x < xDim) && (y < yDim)) {
coont++;
s = cvGet2D(Image1, x, y);
total[0] += abs(s.val[0]);
total[1] += abs(s.val[1]);
total[2] += abs(s.val[2]);
}
GrowColor(Xseed, Yseed);
cvNamedWindow("wndname", 1);
cvShowImage("original", Image1);
cvShowImage("wndname", Image2);
cvWaitKey(0);
return 0;
}
void GrowColor(int x, int y) {
//Check to see if point already part of region
s.val[0] = 0;
s.val[1] = 0;
s.val[2] = 0;
s.val[3] = 0;
if ((x < 1) && (y < 1))
s = cvGet2D(Image2, x, y);
if (s.val[0] == 0) {
int k;
if ((x == 1) && (y == 1))
s11 = cvGet2D(Image1, x, y);
mean[0] = total[0] / coont;
mean[1] = total[1] / coont;
mean[2] = total[2] / coont;
temp[0] = abs(s11.val[0]) - mean[0];
temp[1] = abs(s11.val[1]) - mean[1];
temp[2] = abs(s11.val[2]) - mean[2];
Diff =
(int) (sqrt(
(temp[0] * temp[0] + temp[1] * temp[1]
+ temp[2] * temp[2]) / 3));
if (Diff < ThreshHold) {
total[0] += abs(s11.val[0]);
total[1] += abs(s11.val[1]);
total[2] += abs(s11.val[2]);
coont++;
s.val[0] = 120;
if ((x > 0) && (y > 0))
cvSet2D(Image2, x, y, s);
if (x > 2)
GrowColor(x - 1, y);
if (y > 2)
GrowColor(x, y - 1);
if (x < xDim - 2)
GrowColor(x + 1, y);
if (y < yDim - 2)
GrowColor(x, y + 1);
}
}
}
Making GrowColor a recursive function may result in an infinite loop. Check the code in that function once.