OpenCV Algorithm slows down without reason - opencv

At the moment I am working on a project, which searches a sample in a video stream and constantly check it.
But after a while (sometimes some seconds, sometimes some minutes) it just stops working. No detecting, no video stream.
I checked my processor, and also tried different resolutions. But it's still not working correctly.
#include "pch.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <array>
#include <stdio.h>
#include "opencv2/core/mat.hpp"
using namespace std;
using namespace cv;
/// Create a flag, used for nearly everything
int flag = 0;
int i = 0;
/// BlackPixel counter
float blackPixel;
/// Localizing the best match with minMaxLoc
double minVal, maxVal;
Point minLoc, maxLoc, matchLoc;
/// Punkte für drawMatch
Point middle_x, middle_y;
/// Creating picture Matrix
Mat image_input, image_template, image_display, image_object;
/// Create the result matrix
int result_cols, result_rows;
/// Test Inputs
Mat pictureTest;
Mat objectTest;
string intToString(int number) {
std::stringstream ss;
ss << number;
return ss.str();
}
void drawMatch(Mat object, Mat scene, vector<Point> match_centers)
{
for (size_t i = 0; i < match_centers.size(); i++)
{
/// middle of template at X
middle_x = Point((object.cols / 2) + match_centers[i].x, match_centers[i].y);
/// middle of template at Y
middle_y = Point(match_centers[i].x, match_centers[i].y + (object.rows / 2));
/// Zeichnet Rechteck um Match
rectangle(scene, Point(match_centers[i].x, match_centers[i].y), Point(match_centers[i].x + object.cols, match_centers[i].y + object.rows), Scalar(0, 255, 0), 2);
/// Zeigt das Ergebnis des Tracking
namedWindow("Track", WINDOW_NORMAL);
imshow("Track", scene);
/// Gibt die Koordinaten des Matches im Bild an
//putText(scene, "(" + intToString(match_centers[i].x) + "," + intToString(match_centers[i].y) + ")", Point(match_centers[i].x - 40, match_centers[i].y - 15), 1, 1, Scalar(255, 0, 0));
}
}
vector<Point> imageComparetion(Mat object, Mat scene, int match_method, float peek_percent) {
scene.copyTo(image_display);
object.copyTo(image_object);
result_cols = scene.cols - object.cols + 1;
result_rows = scene.rows - object.rows + 1;
Mat result(result_cols, result_rows, CV_32FC1);
/// match scene with template
matchTemplate(scene, object, result, match_method);
///normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED)
{
matchLoc = minLoc;
threshold(result, result, 0.1, 1, THRESH_BINARY_INV);
}
else
{
matchLoc = maxLoc;
threshold(result, result, 0.9, 1, THRESH_TOZERO);
}
vector<Point> res;
maxVal = 1.f;
Mat input_matrix = image_display; //webcam image into matrix
Mat match = Mat(input_matrix.size(), input_matrix.type(), Scalar::all(0));
while (maxVal > peek_percent) {
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
if (maxVal > peek_percent) {
Rect r1(Point(maxLoc.x - object.cols / 2, maxLoc.y + object.rows / 2), Point(maxLoc.x + object.cols / 2, maxLoc.y - object.rows / 2));
rectangle(result, Point(maxLoc.x - object.cols / 2, maxLoc.y - object.rows / 2), Point(maxLoc.x + object.cols / 2, maxLoc.y + object.rows / 2), Scalar::all(0), -1);
res.push_back(maxLoc);
}
}
return res;
}
int main(int argc, char** argv) {
///open Cam
VideoCapture cap(1);
cap.set(CAP_PROP_FRAME_WIDTH, 1920);
cap.set(CAP_PROP_FRAME_HEIGHT, 1080);
///Check if cam is open
if (!cap.isOpened()) {
cout << "\n Bitte Verbindung zur Kamera ueberpruefen! \n";
return 0;
}
///Read the matches template
image_template = imread("C:/Users/Ceraxes/Pictures/glaspol.jpg");
Mat current = imread("C:/Users/Ceraxes/Pictures/glaspol.jpg");
cap >> image_input;
///find location of template in stream
vector<Point> match_centers = imageComparetion(image_template, image_input, TM_CCOEFF_NORMED, 0.3); //template, picture, matching method, treshold(peak percent)
/// shows the found template
drawMatch(image_template, image_input, match_centers);
waitKey(1);
///build window
namedWindow("IDS", WINDOW_NORMAL);
Mat detect = image_input; //img_display
Mat draw = Mat(detect.size(), detect.type(), Scalar::all(0));
while (true) {
cap >> detect;
///Show image from camera
imshow("IDS", detect);
/// check every found match
while (i < match_centers.size()) {
///Extract the found matches from the picture
Rect r3(Point(match_centers[i].x, match_centers[i].y), Point(match_centers[i].x + image_template.cols, match_centers[i].y + image_template.rows));
///compares the camera imgage with the template
absdiff(detect(r3), current, pictureTest);
///counts the differences
blackPixel = countNonZero(pictureTest == 150);
cout << blackPixel << "\n";
i++;
}
i = 0;
waitKey(1);
}
return 0;
}
I'm using a IDS ueye camera, openCV 4 und Visual Studio 2017.
Does anyone have an idea, why the algorithm slows down?

Related

Edge detection of very small lines using canny/hough

I'm new to opencv. I want to detect very small lines in an image and store them as an array of lines. There will not be more than 10 lines (alignment markers) in my image. I've used a opencv sample tutorial to detect lines using canny and Hough.
For testing, my input image has a set of lines that vary in size: 15, 30, 50, 75 and 100 pixles
The app does not detect the 15 and 30 pixel lines.
It detects 2 of the 4 50 pixel lines.
The 75 and 100 pixel lines are detected fine.
What can I do to detect the 15 and 30 pixel lines?
This is my
Input image
This is my
output image
This is my source
/*
* https://github.com/opencv/opencv/blob/master/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp
*/
/**
* #file HoughLines_Demo.cpp
* #brief Demo code for Hough Transform
* #author OpenCV team
*/
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
/// Global variables
/** General variables */
Mat src, edges;
Mat src_gray;
Mat standard_hough, probabilistic_hough;
int min_threshold = 50;
int max_trackbar = 150;
const char* standard_name = "Standard Hough Lines Demo";
const char* probabilistic_name = "Probabilistic Hough Lines Demo";
int s_trackbar = max_trackbar;
int p_trackbar = max_trackbar;
/// Function Headers
void help();
void Standard_Hough( int, void* );
void Probabilistic_Hough( int, void* );
/**
* #function main
*/
int main( int argc, char** argv )
{
// Read the image
String imageName("../data/building.jpg"); // by default
if (argc > 1)
{
imageName = argv[1];
}
src = imread( imageName, IMREAD_COLOR );
if( src.empty() )
{ help();
return -1;
}
/// Pass the image to gray
cvtColor( src, src_gray, COLOR_RGB2GRAY );
/// Apply Canny edge detector
Canny( src_gray, edges, 50, 200, 3 );
/// Create Trackbars for Thresholds
char thresh_label[50];
sprintf( thresh_label, "Thres: %d + input", min_threshold );
namedWindow( standard_name, WINDOW_AUTOSIZE );
createTrackbar( thresh_label, standard_name, &s_trackbar, max_trackbar, Standard_Hough);
namedWindow( probabilistic_name, WINDOW_AUTOSIZE );
createTrackbar( thresh_label, probabilistic_name, &p_trackbar, max_trackbar, Probabilistic_Hough);
/// Initialize
Standard_Hough(0, 0);
Probabilistic_Hough(0, 0);
waitKey(0);
return 0;
}
/**
* #function help
* #brief Indications of how to run this program and why is it for
*/
void help()
{
printf("\t Hough Transform to detect lines \n ");
printf("\t---------------------------------\n ");
printf(" Usage: ./HoughLines_Demo <image_name> \n");
}
/**
* #function Standard_Hough
*/
void Standard_Hough( int, void* )
{
vector<Vec2f> s_lines;
cvtColor( edges, standard_hough, COLOR_GRAY2BGR );
/// 1. Use Standard Hough Transform
HoughLines( edges, s_lines, 1, CV_PI/180, min_threshold + s_trackbar, 0, 0 );
/// Show the result
for( size_t i = 0; i < s_lines.size(); i++ )
{
float r = s_lines[i][0], t = s_lines[i][1];
double cos_t = cos(t), sin_t = sin(t);
double x0 = r*cos_t, y0 = r*sin_t;
double alpha = 1000;
Point pt1( cvRound(x0 + alpha*(-sin_t)), cvRound(y0 + alpha*cos_t) );
Point pt2( cvRound(x0 - alpha*(-sin_t)), cvRound(y0 - alpha*cos_t) );
line( standard_hough, pt1, pt2, Scalar(255,0,0), 3, LINE_AA);
}
imshow( standard_name, standard_hough );
}
/**
* #function Probabilistic_Hough
*/
void Probabilistic_Hough( int, void* )
{
vector<Vec4i> p_lines;
cvtColor( edges, probabilistic_hough, COLOR_GRAY2BGR );
/// 2. Use Probabilistic Hough Transform
HoughLinesP( edges, p_lines, 1, CV_PI/180, min_threshold + p_trackbar, 30, 10 );
/// Show the result
for( size_t i = 0; i < p_lines.size(); i++ )
{
Vec4i l = p_lines[i];
line( probabilistic_hough, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(255,0,0), 3, LINE_AA);
}
imshow( probabilistic_name, probabilistic_hough );
}
TIA
The variable min_threshold in your code has been set to 50, so it will not consider any line segment candidates smaller than that. With a bit of noise, it is easy for the 50 pixel line segments to get skipped.
You can set this variable to a value less than 15, so that all line segments can be considered.

Regarding a specific Object Detection in OpenCV using WebCam and comparing it with an input Image

I am new to OpenCV and want to develop a program which takes the camera input and compares it with a known image of an object which would be input to it as a .jpg image and if the input of the Webcam matches with the fed in image upto a certain level of accuracy, then some message etc should be displayed that the required object has been found.
Eg: If I get a Computer Cable before the webcam, it needs to be detected and compared to the image of the Computer cable I have fed into the program.
I've tried many techniques and find Template matching to be effective as mentioned in the foll0wing link---
Real-time template matching - OpenCV, C++
However after drawing the rectangle and getting the roiImage..I want to compare its likeliness with a known image on my disk(in the opencv working directory). For this I am trying to convert the roiImg and my other images in HSV format and get 4 values according to the Algorithms.
I have tried to combine the 2 codes but it doesn;t seem to work as roiImg is being made at runtime and is not being able to compare with the other 2 Images using imread.
#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <sstream>
using namespace cv;
using namespace std;
Point point1, point2; /* vertical points of the bounding box */
int drag = 0;
Rect rect; /* bounding box */
Mat img, roiImg; /* roiImg - the part of the image in the bounding box */
int select_flag = 0;
bool go_fast = false;
Mat mytemplate;
Mat src_base, hsv_base;
Mat src_test1, hsv_test1;
Mat src_test2, hsv_test2;
Mat hsv_half_down;
///------- template matching -----------------------------------------------------------------------------------------------
Mat TplMatch( Mat &img, Mat &mytemplate )
{
Mat result;
matchTemplate( img, mytemplate, result, CV_TM_SQDIFF_NORMED );
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
return result;
}
///------- Localizing the best match with minMaxLoc ------------------------------------------------------------------------
Point minmax( Mat &result )
{
double minVal, maxVal;
Point minLoc, maxLoc, matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
matchLoc = minLoc;
return matchLoc;
}
///------- tracking --------------------------------------------------------------------------------------------------------
void track()
{
if (select_flag)
{
//roiImg.copyTo(mytemplate);
// select_flag = false;
go_fast = true;
}
// imshow( "mytemplate", mytemplate ); waitKey(0);
Mat result = TplMatch( img, mytemplate );
Point match = minmax( result );
rectangle( img, match, Point( match.x + mytemplate.cols , match.y + mytemplate.rows ), CV_RGB(255, 255, 255), 0.5 );
std::cout << "match: " << match << endl;
/// latest match is the new template
Rect ROI = cv::Rect( match.x, match.y, mytemplate.cols, mytemplate.rows );
roiImg = img( ROI );
roiImg.copyTo(mytemplate);
imshow( "roiImg", roiImg ); //waitKey(0);
//Compare the roiImg with a know image to calculate resemblence
/*Method Base - Base Base - Half Base - Test 1 Base - Test 2
Correlation 1.000000 0.930766 0.182073 0.120447
Chi-square 0.000000 4.940466 21.184536 49.273437
Intersection 24.391548 14.959809 3.889029 5.775088
Bhattacharyya 0.000000 0.222609 0.646576 0.801869
For the Correlation and Intersection methods, the higher the metric, the more accurate the match. As we can see,
the match base-base is the highest of all as expected. Also we can observe that the match base-half is the second best match (as we predicted).
For the other two metrics, the less the result, the better the match. We can observe that the matches between the test 1 and test 2 with respect
to the base are worse, which again, was expected.)*/
src_base = imread("roiImg");
src_test1 = imread("Samarth.jpg");
src_test2 = imread("Samarth2.jpg");
//double l2_norm = cvNorm( src_base, src_test1 );
/// Convert to HSV
cvtColor( src_base, hsv_base, COLOR_BGR2HSV );
cvtColor( src_test1, hsv_test1, COLOR_BGR2HSV );
cvtColor( src_test2, hsv_test2, COLOR_BGR2HSV );
hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) );
/// Using 50 bins for hue and 60 for saturation
int h_bins = 50; int s_bins = 60;
int histSize[] = { h_bins, s_bins };
// hue varies from 0 to 179, saturation from 0 to 255
float h_ranges[] = { 0, 180 };
float s_ranges[] = { 0, 256 };
const float* ranges[] = { h_ranges, s_ranges };
// Use the o-th and 1-st channels
int channels[] = { 0, 1 };
/// Histograms
MatND hist_base;
MatND hist_half_down;
MatND hist_test1;
MatND hist_test2;
/// Calculate the histograms for the HSV images
calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false );
normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() );
calcHist( &hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false );
normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() );
calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false );
normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() );
calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false );
normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() );
/// Apply the histogram comparison methods
for( int i = 0; i < 4; i++ )
{
int compare_method = i;
double base_base = compareHist( hist_base, hist_base, compare_method );
double base_half = compareHist( hist_base, hist_half_down, compare_method );
double base_test1 = compareHist( hist_base, hist_test1, compare_method );
double base_test2 = compareHist( hist_base, hist_test2, compare_method );
printf( " Method [%d] Perfect, Base-Half, Base-Test(1), Base-Test(2) : %f, %f, %f, %f \n", i, base_base, base_half , base_test1, base_test2 );
}
printf( "Done \n" );
}
///------- MouseCallback function ------------------------------------------------------------------------------------------
void mouseHandler(int event, int x, int y, int flags, void *param)
{
if (event == CV_EVENT_LBUTTONDOWN && !drag)
{
/// left button clicked. ROI selection begins
point1 = Point(x, y);
drag = 1;
}
if (event == CV_EVENT_MOUSEMOVE && drag)
{
/// mouse dragged. ROI being selected
Mat img1 = img.clone();
point2 = Point(x, y);
rectangle(img1, point1, point2, CV_RGB(255, 0, 0), 3, 8, 0);
imshow("image", img1);
}
if (event == CV_EVENT_LBUTTONUP && drag)
{
point2 = Point(x, y);
rect = Rect(point1.x, point1.y, x - point1.x, y - point1.y);
drag = 0;
roiImg = img(rect);
roiImg.copyTo(mytemplate);
// imshow("MOUSE roiImg", roiImg); waitKey(0);
}
if (event == CV_EVENT_LBUTTONUP)
{
/// ROI selected
select_flag = 1;
drag = 0;
}
}
///------- Main() ----------------------------------------------------------------------------------------------------------
int main()
{
int k;
///open webcam
VideoCapture cap(0);
if (!cap.isOpened())
return 1;
/* ///open video file
VideoCapture cap;
cap.open( "Wildlife.wmv" );
if ( !cap.isOpened() )
{ cout << "Unable to open video file" << endl; return -1; }*/
/*
/// Set video to 320x240
cap.set(CV_CAP_PROP_FRAME_WIDTH, 320);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240);*/
cap >> img;
GaussianBlur( img, img, Size(7,7), 3.0 );
imshow( "image", img );
while (1)
{
cap >> img;
if ( img.empty() )
break;
// Flip the frame horizontally and add blur
cv::flip( img, img, 1 );
GaussianBlur( img, img, Size(7,7), 3.0 );
if ( rect.width == 0 && rect.height == 0 )
cvSetMouseCallback( "image", mouseHandler, NULL );
else
track();
imshow("image", img);
// waitKey(100); k = waitKey(75);
k = waitKey(go_fast ? 30 : 10000);
if (k == 27)
break;
}
return 0;
}
if you want to detect a object in live feed , detecting the object in each frame is not efficient .. for the first time you have to detect after you have to track the object.
so this process involving both detection and tracking..
for detection you have to segment the object from the rest, opencv provides many algorithms for segmenting an object from background based on colors color based detection.other than color you can use the objects's shape to segment the object from backgroundshape based segmentation.
you can use lk optical flow algorithm as a starting to tracking.
additionally, you can use template matching or camshift or medial flow tracker.. etc to obtain quick results.all the above algorithm will be useful based on scale change of the object and lighting change of the feed. opencv has sample programs to the above algorithms.

Approximate photo of a simple drawing using lines

As an input I have a photo of a simple symbol, e.g.: https://www.dropbox.com/s/nrmsvfd0le0bkke/symbol.jpg
I would like to detect the straight lines in it, like points of start and ends of the lines. In this case, assuming the top left of the symbol is (0,0), the lines would be defined like this:
start end (coordinates of beginning and end of a line)
1. (0,0); (0,10) (vertical line)
2. (0,10); (15, 15)
3. (15,15); (0, 20)
4. (0,20); (0,30)
How can I do it (pereferably using OpenCV)? I though about Hough lines, but they seem to be good for perfect thin straight lines, which is not the case in a drawing. I'll probably work on binarized image, too.
Give a try on this,
Apply thinning algorithm on threshold image.
Find contours.
approxPolyDP for the found contour.
See some reference:
approxpolydp-for-edge-maps
Creating Bounding boxes and circles for contours
maybe you can work on this one.
assume a perfect binarization:
run HoughLinesP
(not implemented) try to group those detected lines
I used this code:
int main()
{
cv::Mat image = cv::imread("HoughLinesP_perfect.png");
cv::Mat gray;
cv::cvtColor(image,gray,CV_BGR2GRAY);
cv::Mat output; image.copyTo(output);
cv::Mat g_thres = gray == 0;
std::vector<cv::Vec4i> lines;
//cv::HoughLinesP( binary, lines, 1, 2*CV_PI/180, 100, 100, 50 );
// cv::HoughLinesP( h_thres, lines, 1, CV_PI/180, 100, image.cols/2, 10 );
cv::HoughLinesP( g_thres, lines, 1, CV_PI/(4*180.0), 50, image.cols/20, 10 );
for( size_t i = 0; i < lines.size(); i++ )
{
cv::line( output, cv::Point(lines[i][0], lines[i][3]),
cv::Point(lines[i][4], lines[i][3]), cv::Scalar(155,255,155), 1, 8 );
}
cv::imshow("g thres", g_thres);
cv::imwrite("HoughLinesP_out.png", output);
cv::resize(output, output, cv::Size(), 0.5,0.5);
cv::namedWindow("output"); cv::imshow("output", output);
cv::waitKey(-1);
std::cout << "finished" << std::endl;
return 0;
}
EDIT:
updated code with simple line clustering (`minimum_distance function taken from SO):
giving this result:
float minimum_distance(cv::Point2f v, cv::Point2f w, cv::Point2f p) {
// Return minimum distance between line segment vw and point p
const float l2 = cv::norm(w-v) * cv::norm(w-v); // i.e. |w-v|^2 - avoid a sqrt
if (l2 == 0.0) return cv::norm(p-v); // v == w case
// Consider the line extending the segment, parameterized as v + t (w - v).
// We find projection of point p onto the line.
// It falls where t = [(p-v) . (w-v)] / |w-v|^2
//const float t = dot(p - v, w - v) / l2;
float t = ((p-v).x * (w-v).x + (p-v).y * (w-v).y)/l2;
if (t < 0.0) return cv::norm(p-v); // Beyond the 'v' end of the segment
else if (t > 1.0) return cv::norm(p-w); // Beyond the 'w' end of the segment
const cv::Point2f projection = v + t * (w - v); // Projection falls on the segment
return cv::norm(p - projection);
}
int main()
{
cv::Mat image = cv::imread("HoughLinesP_perfect.png");
cv::Mat gray;
cv::cvtColor(image,gray,CV_BGR2GRAY);
cv::Mat output; image.copyTo(output);
cv::Mat g_thres = gray == 0;
std::vector<cv::Vec4i> lines;
cv::HoughLinesP( g_thres, lines, 1, CV_PI/(4*180.0), 50, image.cols/20, 10 );
float minDist = 100;
std::vector<cv::Vec4i> lines_filtered;
for( size_t i = 0; i < lines.size(); i++ )
{
bool keep = true;
int overwrite = -1;
cv::Point2f a(lines[i][0], lines[i][6]);
cv::Point2f b(lines[i][7], lines[i][3]);
float lengthAB = cv::norm(a-b);
for( size_t j = 0; j < lines_filtered.size(); j++ )
{
cv::Point2f c(lines_filtered[j][0], lines_filtered[j][8]);
cv::Point2f d(lines_filtered[j][9], lines_filtered[j][3]);
float distCDA = minimum_distance(c,d,a);
float distCDB = minimum_distance(c,d,b);
float lengthCD = cv::norm(c-d);
if((distCDA < minDist) && (distCDB < minDist))
{
if(lengthCD >= lengthAB)
{
keep = false;
}
else
{
overwrite = j;
}
}
}
if(keep)
{
if(overwrite >= 0)
{
lines_filtered[overwrite] = lines[i];
}
else
{
lines_filtered.push_back(lines[i]);
}
}
}
for( size_t i = 0; i < lines_filtered.size(); i++ )
{
cv::line( output, cv::Point(lines_filtered[i][0], lines_filtered[i][10]),
cv::Point(lines_filtered[i][11], lines_filtered[i][3]), cv::Scalar(155,255,155), 2, 8 );
}
cv::imshow("g thres", g_thres);
cv::imwrite("HoughLinesP_out.png", output);
cv::resize(output, output, cv::Size(), 0.5,0.5);
cv::namedWindow("output"); cv::imshow("output", output);
cv::waitKey(-1);
std::cout << "finished" << std::endl;
return 0;
}
You should try the Hough Line Transform. And here is an example from this website
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("building.jpg", 0);
Mat dst, cdst;
Canny(src, dst, 50, 200, 3);
cvtColor(dst, cdst, CV_GRAY2BGR);
vector<Vec2f> lines;
// detect lines
HoughLines(dst, lines, 1, CV_PI/180, 150, 0, 0 );
// draw lines
for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
line( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
}
imshow("source", src);
imshow("detected lines", cdst);
waitKey();
return 0;
}
With this you should be able to tweak and get the proprieties you are looking for (vertices).

Hough lines tansform opencv program breaks

I am trying to use houghlines transform. The function is working well but program breaks after imshow("detected lines",cdst) somewhere in free.c file in free_base function.
please help me out
Here is my code:
#include<opencv\cv.h>
#include<opencv/cxcore.h>
#include<opencv/highgui.h>
#include<opencv2\imgproc\imgproc.hpp>
#include<iostream>
#include<vector>
#include<math.h>
#include <string>
using namespace cv;
using namespace std;
void help()
{
cout << "\nThis program demonstrates line finding with the Hough transform.\n"
"Usage:\n"
"./houghlines <image_name>, Default is pic1.jpg\n" << endl;
}
int houghline(String filename)
{
//const char* filename = argc >= 2 ? argv[1] : "Release\\D.bmp.bmp";
Mat src = imread(filename, 0);
if(src.empty())
{
help();
cout << "can not open " << filename << endl;
return -1;
}
Mat dst, cdst;
Canny(src, dst, 50, 200, 3);
cvtColor(dst, cdst, CV_GRAY2BGR);
/*
vector<Vec2f> lines;
HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );
float aaa=lines[1][0];
for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
line( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
}
*/
vector<Vec4i> lines;
HoughLinesP(dst, lines, 1, CV_PI/180, 10, 25, 2 );
/*
with the arguments:
dst: Output of the edge detector. It should be a grayscale image (although in fact it is a binary one)
lines: A vector that will store the parameters (x_{start}, y_{start}, x_{end}, y_{end}) of the detected lines
rho : The resolution of the parameter r in pixels. We use 1 pixel.
theta: The resolution of the parameter \theta in radians. We use 1 degree (CV_PI/180)
threshold: The minimum number of intersections to “detect” a line
minLinLength: The minimum number of points that can form a line. Lines with less than this number of points are disregarded.
maxLineGap: The maximum gap between two points to be considered in the same line
*/
for( size_t i = 0; i < lines.size(); i++ )
{
Vec4i l = lines[i];
line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(255,0,0), 1, CV_AA);
imshow("detected lines", cdst);
waitKey();
}
imshow("source", src);
imshow("detected lines", cdst);
}
int main(int argc, char** argv)
{
//for(char alpha='A';alpha<='Z';alpha++)
//String filename="C:\\Users\\Abhinav\\Documents\\Visual Studio 2012\\Projects\\Classes\\Release\\Microsoft Sans Serif\\"+to_string(alpha)+".bmp";
try{houghline("C:\\Users\\Abhinav\\Documents\\Visual Studio 2012\\Projects\\Classes\\Release\\Microsoft Sans Serif\\A.bmp");}
//houghline("C:\\Users\\Abhinav\\Documents\\Visual Studio 2012\\Projects\\Classes\\Release\\Microsoft Sans Serif\\B.bmp");
catch(Exception e){cout<<e.err;}
waitKey();
return 0;
}
It seems that your function "int houghline(String filename)" has no return statement.
Please add "return 0;" at the end of the function and see if it works.

OpenCV Max locations

I am working on an OpenCV project and am using cvMatchTemplate to locate part of an image I am then using cvMinMaxLoc to find the maximum area, therefore best match, my problem is that cvMinMaxLoc only returns one max location were as there may be multiple matches in one image.
Is there any way to return all the max locations above a particular threshold
I.e.
for each location > threshold
add location to array
I'm new to OpenCV and dont know if something like this already exists but so far I haven't been able to find anything
Any help greatly appreciated
I modified the matchTemplate tutorial to get you started. It basically uses a queue to track the top X match points, and later plots all of them. Hope that is helpful!
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <vector>
#include <limits>
#include <queue>
using namespace cv;
using namespace std;
void maxLocs(const Mat& src, queue<Point>& dst, size_t size)
{
float maxValue = -1.0f * numeric_limits<float>::max();
float* srcData = reinterpret_cast<float*>(src.data);
for(int i = 0; i < src.rows; i++)
{
for(int j = 0; j < src.cols; j++)
{
if(srcData[i*src.cols + j] > maxValue)
{
maxValue = srcData[i*src.cols + j];
dst.push(Point(j, i));
// pop the smaller one off the end if we reach the size threshold.
if(dst.size() > size)
{
dst.pop();
}
}
}
}
}
/// Global Variables
Mat img; Mat templ; Mat result;
string image_window = "Source Image";
string result_window = "Result window";
int match_method;
int max_Trackbar = 5;
/// Function Headers
void MatchingMethod( int, void* );
int main(int argc, char* argv[])
{
/// Load image and template
img = imread( "dogs.jpg", 1 );
templ = imread( "dog_templ.jpg", 1 );
/// Create windows
namedWindow( image_window, CV_WINDOW_AUTOSIZE );
namedWindow( result_window, CV_WINDOW_AUTOSIZE );
/// Create Trackbar
string trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );
MatchingMethod( 0, 0 );
waitKey(0);
return 0;
}
/**
* #function MatchingMethod
* #brief Trackbar callback
*/
void MatchingMethod( int, void* )
{
/// Source image to display
Mat img_display;
img.copyTo( img_display );
/// Create the result matrix
int result_cols = img.cols - templ.cols + 1;
int result_rows = img.rows - templ.rows + 1;
result.create( result_cols, result_rows, CV_32FC1 );
/// Do the Matching and Normalize
matchTemplate( img, templ, result, match_method );
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
{
result = 1.0 - result;
}
// get the top 100 maximums...
queue<Point> locations;
maxLocs(result, locations, 100);
/// Show me what you got
while(!locations.empty())
{
Point matchLoc = locations.front();
rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
locations.pop();
}
imshow( image_window, img_display );
imshow( result_window, result );
return;
}
Try cvThreshold(src, dst, threshold, CV_THRESH_BINARY)
This would return an image in dst with all pixels above threshold as white and all others as black. You would then iterate through all the pixels and check if it is greater than 0 then that is a location you want. Something like this
char* data = dst->imageData;
int size = (dst->height) * (dst->width)
for (int i=0; i<size; i++)
{
if(data[i] > 0)
//copy i into your array
}

Resources