How can I use iOpen(), iClose(), iLow() and iHigh() to find these pinbars? - mql4

I want to find the pinbars circled in the attached image below. For the one on the right, the body is about 1/5th of the candle size and for the one on the left, let's say the body is 1/7th the size candle size and it also has a wick of 1/7th the candle size at the bottom. How can I use the iOpen(), iLow() and other similar functions to find these two types of pinbars?

Q : How can I use the iOpen(), iLow() and other similar functions to find these two types of pinbars?
May use a working template like this WasThisTheUserDefinedBearishPATTERN() function and having defined all your user-specific conditions and constants, just call if ( WasThisTheUserDefinedBearishPATTERN( aShift, 4.5, 0.1, 2000 ) ) { do_something(); } when using it for trading:
bool WasThisTheUserDefinedBearishPATTERN( const int aBarNUMBER,
const double aBody2uWICK_MUL,
const double min_FRACTION,
const double MAX_FRACTION
) {
// BAR-UPPER-wick:
double aBarUpWK = ( iHigh( _Symbol, PERIOD_CURRENT, aBarNUMBER )
- iClose( _Symbol, PERIOD_CURRENT, aBarNUMBER )
);
// BAR-body:
double aBarBODY = ( iClose( _Symbol, PERIOD_CURRENT, aBarNUMBER )
- iOpen( _Symbol, PERIOD_CURRENT, aBarNUMBER )
);
// BAR-LOWER-wick:
double aBarLoWK = ( iLow( _Symbol, PERIOD_CURRENT, aBarNUMBER )
- iClose( _Symbol, PERIOD_CURRENT, aBarNUMBER )
);
// FLAG:
bool aBearishFLAG = FALSE;
// -----------------------------------------------------------------
// USER-DEFINE-ABLE SET OF SHAPE-CONDITIONS ..... = add all that apply
// BEARISH BODY:
// has body
// has body BEARISH
// has body not more than about a lo-wick size * < min_FRACTION, MAX_FRACTION >
// has body not less than about a hi-wick size * _MUL
// -------------
if ( aBarBODY >= 0 // not BEARISH
|| aBarUpWK < aBarBODY * aBody2uWICK_MUL // not long enough UpperWICK
){
aBearishFLAG = FALSE; // (NO)
}
else { if ( aBarBODY < 0 // has BEARISH CANDLE
&& ( aBarLoWK == 0 // and may LO-WICK ZERO
|| ( aBarLoWk / aBarBODY > min_FRACTION // .GT. min-WICK-2-BODY-FRACTION
&& aBarLoWk / aBarBODY < MAX_FRACTION // .LT. MAX-WICK-2-BODY-FRACTION
)
)
){ aBearishFLAG = TRUE; } // (YES)
else { aBearishFLAG = FALSE; } // ( NO) OTHERWISE
}
return( aBearishFLAG );
}
Ex-post :
I did WasThisTheUserDefinedBearishPATTERN( aShift, 1, 1/6, 2/6 ) and was expecting it to result in something...
Besides the comment below, kindly also respect The Rules of the World of MQL4 language:
Print( "DIV( 1 / 7 ) == ", 1 / 7 ); // will show you The Rules
Print( "DIV( 1. / 7. ) == ", 1. / 7. ); // will show you The Rules

So the way I would approach this is as follows:
1) What are the characteristics of each candle I am trying to define?
a) Down or up (I prefer 1 or -1)
b) Large rejection tail relative to the body
c) Large rejection tail relative to the non-rejection tail
d) Small body relative to the rejection tail
2) How do we code this in MQL4 using predefined functions?
Let's first make a few assumptions...
First, you are wanting to define these candles in real-time so you can execute when they form.
Second, let's go off the M30 for any given Symbol().
The below function (not tested) will return a 1 when there is a buy signal, and a -1 for a sell signal, and 0 if no signal. You will need to adjust the extern variables accordingly as this is more of a science than a "one-size-fits-all". Also, you might need to use IsNewBar.
//the values below should sum to 100
extern int RTail_To_Range_Ratio = 80; //rejection tail ratio to range of candle
extern int Body_To_Range_Ratio = 10; //body size ratio to range of candle
extern int NRTail_To_Range_Ratio = 10; //non-rejection tail ratio to range of candle
int Signal()
{
//candle information
double dOpen = iOpen(Symbol(),PERIOD_M30,0);
double dHigh = iHigh(Symbol(),PERIOD_M30,0);
double dLow = iLow(Symbol(),PERIOD_M30,0);
double dClose = iClose(Symbol(),PERIOD_M30,0);
double dBody = MathAbs(dOpen - dClose);
double dRange = dHigh - dLow;
double dRTail = 0, dTail = 0;
//green candle
if(dClose > dOPen){
dRTail = dOPen - dLow;
dTail = dHigh - dClose;
//now check ratios
if((dTail / dRange) <= (NRTail_To_Range_Ratio / 100) && (dBody / dRange) <= (Body_To_Range_Ratio / 100) && (dRTail / dRange) >= (RTail_To_Range_Ratio / 100)){
return 1;
}
}
//red candle
else{
dRTail = dHigh - dOpen;
dTail = dClose - dLow;
//now check ratios
if((dTail / dRange) <= (NRTail_To_Range_Ratio / 100) && (dBody / dRange) <= (Body_To_Range_Ratio / 100) && (dRTail / dRange) >= (RTail_To_Range_Ratio / 100)){
return -1;
}
}
return 0;
}
Let me know if this solves your problem #SuperHueman.

Related

How to get a profit of Nth open position MQL4 / MT4?

I want to create a function that can get random profit open position.
For example :
a profit of the Last 2 Open Position of overall Total Position
a profit of the First 3 Open Position of overall Total Position
Below function seems it only gets the First Open Position Profit :
double BuyProfit()
{
Price = 0;
datetime EarliestOrder = TimeCurrent();
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS))
{
if(OrderType() == OP_BUY && OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(EarliestOrder > OrderOpenTime())
{
EarliestOrder = OrderOpenTime();
Price = OrderProfit()+OrderSwap()+OrderCommission();
}
}
}
}
return Price;
}
Q : "How to get a profit of Nth open position MQL4/MT4?I want to create a function that can get random profit open position."
You may take this rapid-prototype to complete your actual logic code:
double nthNetPROFIT( const int Nth ) {
if ( Nth > OrdersTotal() ) return( EMPTY );
int softCount = 0;
double nthNetProfit = EMPTY;,
for( int ii = 0; ii < OrdersTotal(); ii++ ) {
if ( OrderSelect( ii, SELECT_BY_POS ) ) {
if ( OrderType() == OP_BUY // DEPENDS ON ACTUAL LOGIC
&& OrderSymbol() == Symbol() // DEPENDS ON ACTUAL LOGIC
&& OrderMagicNumber() == MagicNumber // DEPENDS ON ACTUAL LOGIC
) {
... // DEPENDS ON ACTUAL LOGIC
if ( ++softCount == Nth ){
nthNetProfit = OrderProfit()
+ OrderSwap()
+ OrderCommission();
break;
}
}
}
return( NormalizeDouble( nthNetProfit, 2 ) );
}

Any MQL4 programmers? What is wrong with this code?

When I try to divide the two doubles in a buffer my indicator blacks out, and the values go extreme in the second window -90000000 and 90000000
#property indicator_separate_window // Îòîáðàæåíèå â îòäåëüíîì îêíå
#property indicator_buffers 3 // Êîëè÷åñòâî áóôåðîâ
#property indicator_color1 Red // Öâåò ïåðâîé ëèíèè
#property indicator_color2 Blue // Öâåò âòîðîé ëèíèè
#property indicator_color3 Green
double FillBuffer[];
double DBuffer[];
double AverageBuffer[];
double H,L;
double point=Point();
int init() // Ñïåöèàëüíàÿ ôóíêöèÿ init()
{
int period = _Period;
string symbol = Symbol();
int digits = _Digits ;
point = _Point ;
if(digits == 5 || digits == 3) { digits = digits - 1 ; point = point * 10 ; }
SetIndexBuffer(0,DBuffer);
SetIndexBuffer(1,FillBuffer);
SetIndexBuffer(2,AverageBuffer);
SetIndexStyle (0,DRAW_LINE,STYLE_SOLID,1);
SetIndexLabel(0, "ADR");
return(INIT_SUCCEEDED);
}
int start()
{
int i, limit, counted_bars;
counted_bars = IndicatorCounted();
//---- check for possible errors
if (counted_bars<0) return(-1);
//---- last counted bar will be recounted
if (counted_bars>0) counted_bars--;
limit = Bars - counted_bars;
for (i = limit; i >= 0; i--)
{
double dbuff= iHigh(NULL,0,i)- iLow(NULL,0,i);
double D0 = iHigh(NULL,0,i+1)- iLow(NULL,0,i+1);
double D1 = iHigh(NULL,0,i+2)- iLow(NULL,0,i+2);
double D2 = iHigh(NULL,0,i+3)- iLow(NULL,0,i+3);
double D3 = iHigh(NULL,0,i+4)- iLow(NULL,0,i+4);
double D4 = iHigh(NULL,0,i+5)- iLow(NULL,0,i+5);
double Average = ((D0+D1+D2+D3+D4)/5)/point;
FillBuffer[i]=dbuff/Average;
}
return(0);
When I try to divide the two values in FillBuffer[] my indicator blacks out. But if I just have either the dbuff or Average in the buffer it will show lines but I want the percentage one is of the other to be printed.
There is not much wrong with the code, but it does not paint the line:
Some polishing may help, but the core logic of the MQL4 Custom Indicator is forgotten in the code. If one does not assign a way, how to plot ( paint ) the line on screen, the GUI will remain "blacked-out" even though the values may have gotten calculated.
Performance warning:
Custom Indicators ( all Custom Indicators ) share one common solo-thread (!!), so proper performance tuning is warmly recommended in this type of MQL4-code-execution blocks.
Some further acceleration might be achieved by reducing / avoiding all the repetitive re-averaging via a sliding-window implementation replacement. While this is not so risky at 5-BARs deep re-processing, for deeper TimeSeries convolutions, the effect is significant and impressive in Strategy Tester accelerated mode of computing's run-times ( getting down to minutes instead of hours ). Worth one's time and efforts.
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 Red
#property indicator_color2 Blue
#property indicator_color3 Green
double FillBuffer[];
double DBuffer[]; // NEVER FILLED IN
double AverageBuffer[]; // NEVER FILLED IN
double point = Point();
int init()
{ int period = _Period; // NEVER CONSUMED
string symbol = Symbol(); // NEVER CONSUMED
int digits = _Digits ; // LOCAL SCOPE ONLY VISIBLE INSIDE init(){...}
point = _Point ;
if ( digits == 5 || digits == 3 ) { digits -= 1;
point *= 10;
}
SetIndexBuffer( 0, DBuffer );
SetIndexBuffer( 1, FillBuffer ); // 1: ASSIGNED, BUT NEVER SET TO HAVE ANY { DRAW_LINE | DRAW_ ... } GUI OUTPUT
SetIndexBuffer( 2, AverageBuffer ); // 2: ASSIGNED, BUT NEVER SET TO HAVE ANY { DRAW_LINE | DRAW_ ... } GUI OUTPUT
SetIndexStyle ( 0, DRAW_LINE, STYLE_SOLID, 1 ); // 0: SET AS DRAW_LINE ( BUT NEVER FILLED IN WITH DATA )
SetIndexLabel( 0, "ADR" );
return( INIT_SUCCEEDED );
}
int start()
{ int i, limit, counted_bars;
counted_bars = IndicatorCounted();
//----check for possible errors
if ( counted_bars < 0 ) return( -1 );
//----last counted bar will be recounted
if ( counted_bars > 0 ) counted_bars--;
limit = ( Bars - 5 ) - counted_bars; // AVOID 1st 5 BARS,
int i0, i1, i2, i3, i4, i5; // WHERE (i+5) WILL OVERFLOW THE TIMESERIES LEFT EDGE
for ( i = limit,
i1 = i + 1,
i2 = i + 2,
i3 = i + 3,
i4 = i + 4,
i5 = i + 5; i >= 0; i--,
i1--,
i2--,
i3--,
i4--,
i5--
)
{ FillBuffer[i] = ( High[i]
- Low[i]
)
/ ( ( High[i1] + High[i2] + High[i3] + High[i4] + High[i5] )
- ( Low[i1] + Low[i2] + Low[i3] + Low[i4] + Low[i5] )
)
/ 5.
/ point;
/* double dbuff = iHigh( NULL, 0, i ) - iLow( NULL, 0, i );
double D0 = iHigh( NULL, 0, i+1 ) - iLow( NULL, 0, i+1 );
double D1 = iHigh( NULL, 0, i+2 ) - iLow( NULL, 0, i+2 );
double D2 = iHigh( NULL, 0, i+3 ) - iLow( NULL, 0, i+3 );
double D3 = iHigh( NULL, 0, i+4 ) - iLow( NULL, 0, i+4 );
double D4 = iHigh( NULL, 0, i+5 ) - iLow( NULL, 0, i+5 );
double Average = ( ( D0 + D1 + D2 + D3 + D4 ) / 5 ) / point;
FillBuffer[i] = dbuff / Average;
*/
}
return( 0 );
}

My First MQL4 EA does not generate any Orders. Why?

I'm trying to build a first EA, code below, but it doesn't execute any trades.
I know it is very simple, but logically, I think this should Buy and Sell.
I'm trying to only use a code that I understand.
I'd appreciate it if anyone had any feedback!
//
extern int sma_short = 10;
extern int sma_long = 20;
extern double fakeout = 0.0005 ;
extern double stoploss = 150;
extern double risk = 1;
extern int slippage = 5;
extern int magicnumber = 12345;
extern bool SignalMail = false;
extern bool UseTrailingStop = true;
extern int TrailingStop = 150;
double sma_short_t3;
double sma_short_t0;
double sma_long_t3;
double sma_long_t0;
double sma_diff_t3;
double sma_diff_t0;
double lots;
double stoplosslevel;
int P = 1;
int ticket, ticket2;
int total = OrdersTotal();
bool OpenLong = false;
bool OpenShort = false;
bool CloseLong = false;
bool CloseShort = false;
bool isYenPair = false;
bool OpenOrder = false;
int OnInit()
{
if ( Digits == 5 || Digits == 3 || Digits == 1 ) P = 10; else P = 1; // To account for 5 digit brokers
if ( Digits == 3 || Digits == 2 ) isYenPair = true; // Adjust for YenPair
return( INIT_SUCCEEDED );
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit( const int reason )
{
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void Start()
{
sma_short_t3 = iMA( NULL, 0, sma_short, 0, MODE_SMA, PRICE_CLOSE, 3 );
sma_short_t0 = iMA( NULL, 0, sma_short, 0, MODE_SMA, PRICE_CLOSE, 0 );
sma_long_t3 = iMA( NULL, 0, sma_long, 0, MODE_SMA, PRICE_CLOSE, 3 );
sma_long_t0 = iMA( NULL, 0, sma_long, 0, MODE_SMA, PRICE_CLOSE, 0 );
sma_diff_t3 = sma_long_t3 - sma_short_t3;
sma_diff_t0 = sma_long_t0 - sma_short_t0;
if ( OpenOrder )
{
if ( CloseLong || CloseShort )
{
OrderClose( OrderTicket(), OrderLots(), Bid, slippage, MediumSeaGreen );
OpenOrder = False;
CloseLong = False;
CloseShort = False;
}
}
if ( sma_diff_t3 < 0 && sma_diff_t0 > fakeout )
{
OpenLong = True ;
CloseShort = True;
}
if ( sma_diff_t3 > 0 && sma_diff_t0 < -fakeout )
{
OpenShort = True;
CloseLong = True;
}
lots = risk * 0.01 * AccountBalance() / ( MarketInfo( Symbol(), MODE_LOTSIZE ) * stoploss * P * Point ); // Sizing Algo based on account size
if ( isYenPair == true ) lots = lots * 100; // Adjust for Yen Pairs
lots = NormalizeDouble( lots, 2 );
if ( OpenLong )
{
stoplosslevel = Ask - stoploss * Point * P;
OrderSend( Symbol(), OP_BUY, lots, Ask, slippage, stoplosslevel, 0, "Buy(#" + magicnumber + ")", magicnumber, 0, DodgerBlue );
OpenOrder = True;
}
if ( OpenShort )
{
stoplosslevel = Bid + stoploss * Point * P;
OrderSend( Symbol(), OP_SELL, lots, Ask, slippage, stoplosslevel, 0, "Buy(#" + magicnumber + ")", magicnumber, 0, DodgerBlue );
OpenOrder = True ;
}
}
//+------------------------------------------------------------------+
and why do you use (MarketInfo(Symbol(),MODE_LOTSIZE)? what is the idea of that? first try with double lots = 1.00; and if problem still exists - please add a line telling about the reason why ea failed to send. sth like int ticket = OrderSend(***); if(ticket<0)Print("error=",GetLastError()); or more complex telling about the actual prices, lots, stoploss etc.
Few things in MQL4 to rather get used to:
All PriceDOMAIN data has to be NormalizeDouble() before sending to MetaTrader 4 Server.
All EquityDOMAIN data has to follow a set of discrete values,having MathMin( aMinLOT_SIZE + N * aMinLOT_STEP, aMaxLOT_SIZE ). Normalisation of EquityDOMAIN data is broker-specificand instrument-specific, so need not be always 2.
For XTO, OrderSend(), OrderMOdify(), OrderClose(), one ought follow something like this:
if ( OpenLong )
{ stoplosslevel = NormalizeDouble( Ask - stoploss * Point * P, _Digits ); // ALWAYS NormalizeDouble()
int RetCODE = OrderSend( _Symbol,
OP_BUY,
lots,
Ask,
slippage,
stoplosslevel,
0,
"Buy(#" + magicnumber + ")",
magicnumber,
0,
DodgerBlue
);
if ( RetCODE < 0 )
{ Print( "EXC: Tried to go LONG, OrderSend() failed to get confirmed ( Errno: ", GetLastError(), " )" );
}
else
{ OpenOrder = True;
...
}
...
}

How to accumulate and retain records in Buffer[] - in a MQL4 Custom Indicator?

I am making a custom indicator, that displays the change in the closing price of a certain currency.
for ( i = limit; i >= 0; i-- ) {
totaleur = 0;
for ( x = i; x < i + 1; x++ ) {
totaleur = ( ( iClose( "EURUSD", 0, x )
- iClose( "EURUSD", 0, x - 1 )
)
/ iClose( "EURUSD", 0, x - 1 )
);
}
ExtMapBuffer1[i] = totaleur;
return(0);
}
in this case the indicator displays only the change in price of each observation.
Any ideas how to make it display the change in an observation plus all previous observations?
There are several important points to realise, so as to make the goal achieved:
1: do not prematurely escape in the first round, via return(0)
moving the command return(0); outside the code-execution block {...}from the forward-stepping ( i decreases ) for( i = limit ;...; i--){...} code-execution block will let the pointer step forward in (i),as the Custom Indicator uses a progressive, discontinuous, per-partes incremental ( in time ), evaluation ( ref. MQL4 documentation on Custom Indicator iCustom(...) calling interface parameters )
2: decide, whether the inner-loop ( a sum of fractions ) was correctly coded
the proposed expression providesa sum of N, per-Bar relative differences,nota sum of N absolute-differences, divided by a net price change over N bars.
While this might be working, the point is, whether the intended model is correct to sum relative differences ( percent change over different, variable individual bases ), or whether the sum ob absolute differences ought be only at the very end of the loop divided by a one, common, base -- the net price difference between the first and the last point ( over the N-bars base ), which is commonly a quantitative modelling practice when a noisy signal is subject to some cheap smoothing technique.
3: correct problems in accessing TimeSeries vectors ( negative index )
given the outer for ( i = limit; i >= 0; i-- ) loop permits the i to become zero,
given the inner for ( x = i; ... ) thus permits x == 0,
the x - 1 < 0 becomes a problem,
wherethe instruction iClose( _Symbol, PERIOD_CURRENT, x - 1 ) requests to access a value, that does not yet exist ( has a negative index into TimeSeries vector ).
for ( i = limit; // SET:_______________________ START at BAR[i == limit]
i >= 0; // PRE: PRE-CONDITION i >= 0
i-- // UPD: POST-UPDATE i-- STEP FORWARD IN TIME
) { // ___________________________________________________________
totaleur = 0; // ZEROISED
for ( x = i; // SET:_________________ START at BAR[x = (i)]
x < i + 1; // PRE: PRE-CONDITION x < (i)+1
x++ // UPD: POST-UPDATE x++ +1 STEP ( ONCE )
) { // _____________________________________________________
totaleur = ( ( iClose( "EURUSD", 0, x )
- iClose( "EURUSD", 0, x - 1 )
)
/ iClose( "EURUSD", 0, x - 1 )
);
} // LOOP KEPT STORING ANY INTERIM VALUE FOR EACH x INTO THE SAME <var>
ExtMapBuffer1[i] = totaleur;
return(0); //___________________________________DO NOT PREMATURELY RET/EXIT RIGHT FROM THE 1st LOOP
}
As you might have already noticed, the code permits just one loop in the inner for(){...}
If you need a sum of N previous observations - you need something like this:
for(i=limit; i>=0; i--) {
double totaleur = 0;
for(x=i; x<i+N; x++) {
totaleur += ((iClose("EURUSD", 0, x)- iClose("EURUSD", 0, x-1))/iClose("EURUSD", 0, x-1));
}
ExtMapBuffer1[i]=totaleur;
}
when you have return(0); inside loop - indicator will stop there and do not run that cycle with next parameter - so be careful with it

OpenCV: get Hough accumulator value?

Is it possible to get the accumulator value along with rho and theta from a Hough transform?
I ask because I'd like to differentiate between lines which are "well defined" (ie, which have a high accumulator value) and lines which aren't as well defined.
Thanks!
Ok, so looking at the cvhough.cpp file, the structure CvLinePolar is only defined by rho and angle.
This is all that is passed back as a result of our call to HoughLines. I am in the process of modifying the c++ file and see if i can get the votes out.
Update oct 26: just realized these are not really answers but more like questions. apparently frowned upon. I found some instructions on recompiling OpenCV. I guess we'll have to go in the code and modify it and recompile.
How to install OpenCV 2.0 on win32
update Oct 27: well, i failed at compiling the dlls for OpenCV with my new code so I ended up copy-pasting the specific parts I want to modify into my own files.
I like to add new functions so to avoid overloading the already defined functions.
There are 4 main things you need to copy over:
1- some random defines
#define hough_cmp_gt(l1,l2) (aux[l1] > aux[l2])
static CV_IMPLEMENT_QSORT_EX( icvHoughSortDescent32s, int, hough_cmp_gt, const int* )
2- redefining the struct for line parameters
typedef struct CvLinePolar2
{
float rho;
float angle;
float votes;
}
CvLinePolar2;
3- the main function that was modified
static void
icvHoughLinesStandard2( const CvMat* img, float rho, float theta,
int threshold, CvSeq *lines, int linesMax )
{
cv::AutoBuffer<int> _accum, _sort_buf;
cv::AutoBuffer<float> _tabSin, _tabCos;
const uchar* image;
int step, width, height;
int numangle, numrho;
int total = 0;
float ang;
int r, n;
int i, j;
float irho = 1 / rho;
double scale;
CV_Assert( CV_IS_MAT(img) && CV_MAT_TYPE(img->type) == CV_8UC1 );
image = img->data.ptr;
step = img->step;
width = img->cols;
height = img->rows;
numangle = cvRound(CV_PI / theta);
numrho = cvRound(((width + height) * 2 + 1) / rho);
_accum.allocate((numangle+2) * (numrho+2));
_sort_buf.allocate(numangle * numrho);
_tabSin.allocate(numangle);
_tabCos.allocate(numangle);
int *accum = _accum, *sort_buf = _sort_buf;
float *tabSin = _tabSin, *tabCos = _tabCos;
memset( accum, 0, sizeof(accum[0]) * (numangle+2) * (numrho+2) );
for( ang = 0, n = 0; n < numangle; ang += theta, n++ )
{
tabSin[n] = (float)(sin(ang) * irho);
tabCos[n] = (float)(cos(ang) * irho);
}
// stage 1. fill accumulator
for( i = 0; i < height; i++ )
for( j = 0; j < width; j++ )
{
if( image[i * step + j] != 0 )
for( n = 0; n < numangle; n++ )
{
r = cvRound( j * tabCos[n] + i * tabSin[n] );
r += (numrho - 1) / 2;
accum[(n+1) * (numrho+2) + r+1]++;
}
}
// stage 2. find local maximums
for( r = 0; r < numrho; r++ )
for( n = 0; n < numangle; n++ )
{
int base = (n+1) * (numrho+2) + r+1;
if( accum[base] > threshold &&
accum[base] > accum[base - 1] && accum[base] >= accum[base + 1] &&
accum[base] > accum[base - numrho - 2] && accum[base] >= accum[base + numrho + 2] )
sort_buf[total++] = base;
}
// stage 3. sort the detected lines by accumulator value
icvHoughSortDescent32s( sort_buf, total, accum );
// stage 4. store the first min(total,linesMax) lines to the output buffer
linesMax = MIN(linesMax, total);
scale = 1./(numrho+2);
for( i = 0; i < linesMax; i++ )
{
CvLinePolar2 line;
int idx = sort_buf[i];
int n = cvFloor(idx*scale) - 1;
int r = idx - (n+1)*(numrho+2) - 1;
line.rho = (r - (numrho - 1)*0.5f) * rho;
line.angle = n * theta;
line.votes = accum[idx];
cvSeqPush( lines, &line );
}
cvFree( (void**)&sort_buf );
cvFree( (void**)&accum );
cvFree( (void**)&tabSin );
cvFree( (void**)&tabCos);
}
4- the function that calls that function
CV_IMPL CvSeq*
cvHoughLines3( CvArr* src_image, void* lineStorage, int method,
double rho, double theta, int threshold,
double param1, double param2 )
{
CvSeq* result = 0;
CvMat stub, *img = (CvMat*)src_image;
CvMat* mat = 0;
CvSeq* lines = 0;
CvSeq lines_header;
CvSeqBlock lines_block;
int lineType, elemSize;
int linesMax = INT_MAX;
int iparam1, iparam2;
img = cvGetMat( img, &stub );
if( !CV_IS_MASK_ARR(img))
CV_Error( CV_StsBadArg, "The source image must be 8-bit, single-channel" );
if( !lineStorage )
CV_Error( CV_StsNullPtr, "NULL destination" );
if( rho <= 0 || theta <= 0 || threshold <= 0 )
CV_Error( CV_StsOutOfRange, "rho, theta and threshold must be positive" );
if( method != CV_HOUGH_PROBABILISTIC )
{
lineType = CV_32FC3;
elemSize = sizeof(float)*3;
}
else
{
lineType = CV_32SC4;
elemSize = sizeof(int)*4;
}
if( CV_IS_STORAGE( lineStorage ))
{
lines = cvCreateSeq( lineType, sizeof(CvSeq), elemSize, (CvMemStorage*)lineStorage );
}
else if( CV_IS_MAT( lineStorage ))
{
mat = (CvMat*)lineStorage;
if( !CV_IS_MAT_CONT( mat->type ) || (mat->rows != 1 && mat->cols != 1) )
CV_Error( CV_StsBadArg,
"The destination matrix should be continuous and have a single row or a single column" );
if( CV_MAT_TYPE( mat->type ) != lineType )
CV_Error( CV_StsBadArg,
"The destination matrix data type is inappropriate, see the manual" );
lines = cvMakeSeqHeaderForArray( lineType, sizeof(CvSeq), elemSize, mat->data.ptr,
mat->rows + mat->cols - 1, &lines_header, &lines_block );
linesMax = lines->total;
cvClearSeq( lines );
}
else
CV_Error( CV_StsBadArg, "Destination is not CvMemStorage* nor CvMat*" );
iparam1 = cvRound(param1);
iparam2 = cvRound(param2);
switch( method )
{
case CV_HOUGH_STANDARD:
icvHoughLinesStandard2( img, (float)rho,
(float)theta, threshold, lines, linesMax );
break;
default:
CV_Error( CV_StsBadArg, "Unrecognized method id" );
}
if( mat )
{
if( mat->cols > mat->rows )
mat->cols = lines->total;
else
mat->rows = lines->total;
}
else
result = lines;
return result;
}
And i guess you could uninstall opencv so it takes off all those automatic path setting and recompile it yourself using the CMake method and then the OpenCV is really whatever you make it.
Although this is an old question, I had the same problem, so I might as well put up my solution. The threshold in houghlines() returns 1 for any point that cleared the threshold for votes. The solution is to run houghlines() for every threshold value (until there are no more votes) and add up the votes in another array. In python (maybe with other languages too) when you have no more votes, it throws an error, so use try/except.
Here is an example in python. The array I used was for rho values of -199 to 200 with a max vote of less than 100. You can play around with those constants to suit your needs. You may need to add a line to convert the source image to grayscale.
import matplotlib.pyplot as plt
import cv2
import math
############ make houghspace array ############
houghspace = []
c = 0
height = 400
while c <= height:
houghspace.append([])
cc = 0
while cc <= 180:
houghspace[c].append(0)
cc += 1
c+=1
############ do transform ############
degree_tick = 1 #by how many degrees to check
total_votes = 1 #votes counter
highest_vote = 0 #highest vote in the array
while total_votes < 100:
img = cv2.imread('source.pgm')
edges = cv2.Canny(img,50,150,apertureSize = 3)
lines = cv2.HoughLines(edges,1,math.pi*degree_tick/180,total_votes)
try:
for rho,theta in lines[0]:
a = math.cos(theta)
b = math.sin(theta)
x1 = int((a*rho) + 1000*(-b))
y1 = int((b*rho) + 1000*(a))
x2 = int((a*rho) - 1000*(-b))
y2 = int((b*rho) - 1000*(a))
cv2.line(img,(x1,y1),(x2,y2),(50,200,255),2)
#################add votes into the array################
deradian = 180/math.pi #used to convert to degrees
for rho,theta in lines[0]:
degree = int(round(theta*deradian))
rho_pos = int(rho - 200)
houghspace[rho_pos][degree] += 1
#when lines[0] has no votes, it throws an error which is caught here
except:
total_votes = 999 #exit loop
highest_vote = total_votes
total_votes += 1
del lines
########### loop finished ###############################
print highest_vote
#############################################################
################### plot the houghspace ###################
maxy = 200 #used to offset the y-axis
miny = -200 #used to offset the y-axis
#the main graph
fig = plt.figure(figsize=(10, 5))
ax = fig.add_subplot(111)
ax.set_title('Houghspace')
plt.imshow(houghspace, cmap='gist_stern')
ax.set_aspect('equal')
plt.yticks([0,-miny,maxy-miny], [miny,0,maxy])
#the legend
cax = fig.add_axes([0, 0.1, 0.78, 0.8])
cax.get_xaxis().set_visible(False)
cax.get_yaxis().set_visible(False)
cax.patch.set_alpha(0)
cax.set_frame_on(False)
plt.colorbar(orientation='vertical')
#plot
plt.show()

Resources