Forum Index
HomeZBasic Home   Forum RulesForum Rules   Forum FAQForum FAQ   MemberlistMemberlist   UsergroupsUsergroups   RSS FeedRSS Feed
Site SearchSite Search   LinksLinks   DownloadDownload   Digests and SubscriptionsDigests and Subscriptions
ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in   RegisterRegister
Simple NTSC video object tracking, I think
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Forum Index -> General
Author Message
GTBecker



Joined: 18 Jan 2006
Posts: 457
Location: Cape Coral

Posted: 18 December 2009, 2:21 AM    Post subject: Simple NTSC video object tracking, I think Reply with quote

Please allow me to pick your brains once again, gentlemen.

I want to center a small, high-contrast monochrome object in an NTSC video image by steering the NTSC mono camera platform in the direction of the frame-center-to-object vector. For initial simplicity, there will be no other objects in an otherwise black frame.

That is, if the object is equally to the right and above the frame center, the camera must steer a +45 degree path. If the object is directly below the center, it must steer 180 degrees. Once centered the camera will hunt the object, tracking it as it moves.

Were this to be done with a processor studying a digitized frame it would be easy, but that requires a frame store, lots of data and speed. Instead, I want to do this with no image digitization - perhpas with just a luminance threshold comparison and a sync separator like an LM1881.

I'm thinking I can use a pair of interrupts to count horizontal sync pulses from the top of a frame (the vertical sync pulse), and time the comparator output pulse displacement from the frame's left edge (the horizontal sync pulse). Once per frame, the processor would use those two values to calculate an arctangent.

Anyone think of gotchas?
Back to top
twesthoff



Joined: 17 Mar 2006
Posts: 191
Location: Fredericksburg, VA

Posted: 18 December 2009, 3:48 AM    Post subject: Simple NTSC video object tracking, I think Reply with quote

On 12/17/2009 9:21 PM, General wrote:
Quote:
Please allow me to pick your brains once again, gentlemen.

I want to center a small, high-contrast monochrome object in an NTSC video image by steering the NTSC mono camera platform in the direction of the frame-center-to-object vector. For initial simplicity, there will be no other objects in an otherwise black frame.

That is, if the object is equally to the right and above the frame center, the camera must steer a +45 degree path. If the object is directly below the center, it must steer 180 degrees. Once centered the camera will hunt the object, tracking it as it moves.

Were this to be done with a processor studying a digitized frame it would be easy, but that requires a frame store, lots of data and speed. Instead, I want to do this with no image digitization - perhpas with just a luminance threshold comparison and a sync separator like an LM1881.

I'm thinking I can use a pair of interrupts to count horizontal sync pulses from the top of a frame (the vertical sync pulse), and time the comparator output pulse displacement from the frame's left edge (the horizontal sync pulse). Once per frame, the processor would use those two values to calculate an arctangent.

You could also just time from the vertical sync pulse too, just like you propose for the horizontal, just slower.  Years ago I did that with op-amps working as comparators.  That gated pulses that were counted by the processor.  Shouldn't be a problem I wouldn't think.
Quote:

Anyone think of gotchas?



Tom




Back to top
GTBecker



Joined: 18 Jan 2006
Posts: 457
Location: Cape Coral

Posted: 18 December 2009, 17:10 PM    Post subject: Re: Simple NTSC video object tracking, I think Reply with quote

twesthoff wrote:
... just time from the vertical sync pulse...


Quite right, even simpler. Thanks.
Back to top
GTBecker



Joined: 18 Jan 2006
Posts: 457
Location: Cape Coral

Posted: 23 December 2009, 4:32 AM    Post subject: Reply with quote

It works! Not perfect but not bad: http://www.ustream.tv/recorded/3354535

This is an IR NTSC camera feeding a MAX7456 OSD that I used for convenience to get a vertical sync pulse (an LM1881 should do), a comparator and a flipflop (I used a TLC555 as one). The flipflop yields a pulse width from sync to video peak, which is timed with InputCapture and converted to lines, then rows and columns to place the tracking cursor.

Getting a vector from center-screen to the object (a cotton ball on a small flashlight here), now looks easy.
Back to top
twesthoff



Joined: 17 Mar 2006
Posts: 191
Location: Fredericksburg, VA

Posted: 23 December 2009, 12:29 PM    Post subject: Simple NTSC video object tracking, I think Reply with quote

Looks great!  Keep us informed as to your progress.  I'd like to see how good it gets after you tweak it some.


On 12/22/2009 11:32 PM, General wrote:
Quote:
It works! Not perfect but not bad: http://www.ustream.tv/recorded/3354535

This is an IR NTSC camera feeding a MAX7456 OSD that I used for convenience to get a vertical sync pulse (an LM1811 will do), a comparator and a flipflop (I used a TLC555 as one). The flipflop yields a pulse width from sync to video peak, which is timed with InputCapture and converted to lines, then rows and columns to place the tracking cursor.

Getting a vector from center-screen to the object (a cotton ball on a small flashlight here), now looks easy.



Tom




Back to top
GTBecker



Joined: 18 Jan 2006
Posts: 457
Location: Cape Coral

Posted: 27 December 2009, 2:31 AM    Post subject: Reply with quote

Better and simpler.

The IR camera is now in non-interlaced mode (three tiny, but adjacent, bridged pins) which eliminates half-line errors, and I DC-coupled the video output. The timing IC on the camera board provides sync signals, so no sync separator is needed.

Vertical sync sets a flop; a video signal height comparator resets it. InputCaptureEx times the flop output. An SPI digital pot sets the comparator threshold, finding the brightest object.

I found that the IC also has a two-wire serial interface that can set the shutter speed, and the AGC loop can be broken to keep the camera out of saturation.

This demo shows the flop timing reduced to an X/Y grid - Y based on scan lines, X based on equivalent timing - and the center-screen to object vector angle and relative video peak. Only the vector angle is necessary to center the object.

Very encouraging.

http://www.ustream.tv/recorded/3490946
Back to top
pdubinsky



Joined: 25 Nov 2005
Posts: 66
Location: South Carolina

Posted: 01 January 2010, 19:59 PM    Post subject: MAX7456 Implemantation Reply with quote

Tom, your projects always impress me. Very cool!

Coincidentally, I'm fighting to get an uncooperative MAX7456 to communicate with a ZX24N. Care to share your SPI code and hookup so I can get my circuit working?

Thanks, and Happy New Year,
Paul
Back to top
GTBecker



Joined: 18 Jan 2006
Posts: 457
Location: Cape Coral

Posted: 02 January 2010, 0:14 AM    Post subject: Reply with quote

Here is a MAX7456 demo for ZX-24. This should need only MOSI, MISO, SCLK and /CS to ZX-24 pin 6, with a pullup on /CS (not required on a ZX-24n, I imagine). No video-in is necessary since the 7456 will revert to internal sync without it.

OSD functions I didn't need aren't are implemented here, but most are. I haven't compiled it for a ZX-24n, but I think it should be fine as is.



Code:
' ' MAX7456 for ZX-24
' GTBecker 2009-12-19 2010-01-01

   const pinOSD_SPI_CSNot as byte = 6
   const OSD_SPIChannel as byte = 1

   const bRead as byte = &h80   ' read address offset
   const regVM0 as byte = 0
   const regVM1 as byte = 1
   const regDMM as byte = 4
   const regDMAH as byte = 5
   const regDMAL as byte = 6
   const regDMDI as byte = 7
   const regCMM as byte = 8
   const regCMAH as byte = 9
   const regCMAL as byte = &h0A
   const regCMDI as byte = &h0B
   const regOSDBL as byte = &h6C
   const regSTAT as byte = &hA0
   const regDMDO as byte = &hB0
   const regCMDO as byte = &hC0

   ' 32 special OSD chars start at ASCII &h00, ASCII-to-OSD char table starts at ASCII &h20
   dim OSDCharTable as bytevectordata ({&h42,&h42,&h42,&h42,&h42,&h42,&h42,&h42, _
            &h42,&h42,&hEA,&hEB,&hec,&hed,&hee,&hef, _   ' =, degree...
            &hf0,&hf1,&hf2,&hf3,&hf4,&hf5,&hf6,&hf7, _
            &hf8,&hf9,&hfa,&hfb,&hfc,&hfd,&hfe,&hff, _
            &h00,&h42,&h48,&h42,&h42,&h42,&h42,&h46, _   ' space - '
            &h3f,&h40,&h42,&h42,&h45,&h49,&h41,&h47, _   ' ( - /
            &h0A,&h01,&h02,&h03,&h04,&h05,&h06,&h07, _   ' 0 - 7
            &h08,&h09,&h44,&h43,&h4a,&h42,&h4b,&h42, _   ' 8 - ?
            &h4c,&h0b,&h0c,&h0d,&h0e,&h0f,&h10,&h11, _   ' @ - G
            &h12,&h13,&h14,&h15,&h16,&h17,&h18,&h19, _    ' H - O
            &h1a,&h1b,&h1c,&h1d,&h1e,&h1f,&h20,&h21, _    ' P - W   
            &h22,&h23,&h24,&h42,&h42,&h42,&h42,&h42, _    ' X - _   
            &h42,&h25,&h26,&h27,&h28,&h29,&h2a,&h2b, _    ' ` - g   
            &h2c,&h2d,&h2e,&h2f,&h30,&h31,&h32,&h33, _    ' h - o   
            &h34,&h35,&h36,&h37,&h38,&h39,&h3a,&h3b, _    ' p - w   
            &h3c,&h3d,&h3e,&h42,&h42,&h42,&h42,&h42})   ' x - ~   
   
   ' custom characters loaded to OSD NVM   
   const CharDegreeOSDAddress as byte = &hEB   ' used as &h0B in OSDCharTable
   dim CharDegree as bytevectordata ({&h55, &h55, &h55, &h55, &h00, &h55, &h54, &hAA, &h15, _
            &h52, &hAA, &h85, &h4A, &h00, &hA1, &h4A, &h14, &hA1, _
            &h4A, &h14, &hA1, &h4A, &h00, &hA1, &h52, &hAA, &h85, _
            &h54, &hAA, &h15, &h55, &h00, &h55, &h55, &h55, &h55, _
            &h55, &h55, &h55, &h55, &h55, &h55, &h55, &h55, &h55, _
            &h55, &h55, &h55, &h55, &h55, &h55, &h55, &h55, &h55})
   const CharEqualsOSDAddress as byte = &hEA   ' used as &h0A in OSDCharTable
   dim CharEquals as bytevectordata ({&h55, &h55, &h55, &h55, &h55, &h55, &h55, &h55, &h55, _
            &h55, &h55, &h55, &h55, &h55, &h55, &h55, &h55, &h55, _
            &h50, &h00, &h15, &h4A, &hAA, &h85, &h4A, &hAA, &h85, _
            &h50, &h00, &h15, &h50, &h00, &h15, &h4A, &hAA, &h85, _
            &h4A, &hAA, &h85, &h50, &h00, &h15, &h55, &h55, &h55, _
            &h55, &h55, &h55, &h55, &h55, &h55, &h55, &h55, &h55})
            
   const OSDRowCount as integer = 13
   const OSDColumnCount as integer = 30
   const TVFirstRow as integer = 1      ' OSD row zero is offscreen on my CRT TV
   const TVFirstColumn as integer = 1
   const TVColumnCount as integer = 27   ' first column and last three are offscreen on my TV

   dim Count as byte
      
Sub Main()
    call Sleep(1.0)
   call putpin(pinOSD_SPI_CSNot, zxOutputHigh)
   call OpenSPI(OSD_SPIChannel, 0, pinOSD_SPI_CSNot)
   call OSD8BitWrite(&hff)      ' end autoincrement if it's left on
   call WriteOSDReg(regVM0, zx0000_0010)      ' soft reset
   call sleep(1)
   call LoadOSDCharacter(CharDegreeOSDAddress, CharDegree(1).DataAddress)   ' degree symbol to OSD
   call LoadOSDCharacter(CharEqualsOSDAddress, CharEquals(1).DataAddress)    ' equals symbol
   call ModifyOSDReg(regOSDBL, &h10, &h10)   ' automatic black level on
   call WriteOSDReg(regVM0, zx0000_1000)   ' enable OSD

   call ShowCharOnOSD(6, 14, &h3C)   ' "x" (OSD NVM addressing)   ' ~center screen
   call ShowStringOnTV(0, 1, "Custom degree symbol: " & chr(&h0B))   ' text through translation table
   do   
      Count = Count + 1
      call ShowStringOnTV(9, 9, "Count" & chr(&h0a) & cstr(Count) & "  ")   ' Count =
      call ShowMeter(10, csng(Count) / 255.0)   ' ShowMeter bar displays 0.0 - 1.0
   loop
end sub

sub WriteOSDReg(byval bAddress as byte, byval bData as byte)
   dim bOSD_Command(1 to 2) as byte
   bOSD_Command(1) = bAddress      ' set register write address
   bOSD_Command(2) = bData         ' set register data
   call SPIcmd(OSD_SPIChannel, 2, bOSD_Command(1), 0, 0)
end sub

sub OSD8BitWrite(byval bData as byte)
   call SPIcmd(OSD_SPIChannel, 1, bData, 0, 0)
end sub

sub ModifyOSDReg(byval bAddress as byte, byval bData as byte, byval bMask as byte)
   call WriteOSDReg(bAddress, (ReadOSDReg(bAddress) and not bMask) OR (bData and bMask))   ' set register data
end sub

function ReadOSDReg(byval bAddress as byte) as byte
   dim bOSD_Command as byte, bOSD_Response as byte
   bOSD_Command = bAddress or bRead   ' set register read address
   call SPIcmd(OSD_SPIChannel, 1, bOSD_Command, 1, bOSD_Response)
   ReadOSDReg = bOSD_Response
end function

sub ShowCharOnOSD(byval Row as integer, byval Column as integer, byval Char as byte)
   dim OSDAddr as integer
   OSDAddr = Row * OSDColumnCount + Column
   call WriteOSDReg(regDMAH, hibyte(OSDAddr) and 1)
   call WriteOSDReg(regDMAL, lobyte(OSDAddr))
   call WriteOSDReg(regDMDI, Char)
end sub

sub ShowStringOnTV(byval TVLine as integer, byval TVColumn as integer, byval ASCII as string)
   dim OSDAddr as integer
   OSDAddr = ((TVLine + TVFirstRow) * OSDColumnCount + TVColumn + TVFirstColumn) mod (OSDColumnCount * OSDRowCount)
   call WriteOSDReg(regDMAH, 0)
   call WriteOSDReg(regDMAH, hibyte(OSDAddr) and 1)
   call WriteOSDReg(regDMAL, lobyte(OSDAddr))
   call WriteOSDReg(regDMM, zx0100_0001)      ' 8-bit, autoincrement
   dim i as integer
   for i = 1 to len(ASCII)
      call OSD8BitWrite(OSDCharTable(asc(mid(ASCII, i, 1)) + 1))
   next
   call OSD8BitWrite(&hff)   ' end autoincrement
end sub

sub LoadOSDCharacter(byval OSDAddress as byte, byval DataAddr as Long)
   dim i as byte, b as byte
   call WriteOSDReg(regCMAH, OSDAddress)   ' OSD character address
   for i = 0 to 53      ' 54 bytes of character pixel data
      call WriteOSDReg(regCMAL, i)   ' 4-pixels address
      call GetProgMem(DataAddr + clng(i), b, 1)
      call WriteOSDReg(regCMDI, b)   ' load 4 pixels to shadow ram
   next   ' for 18 rows
   call WriteOSDReg(regCMM, zx1010_0000)      ' load NVM from shadow ram
   call sleep(0.015)
end sub

sub ShowMeter(byval Line as integer, byval MeterValue as single)
   dim i as integer, MV as integer, Meter as string*25
   Meter = ""
   for i = 1 to 25
      MV = cint(MeterValue * 100.0)
      if ((i * 4) - 1) < MV then
         mid(Meter, i, 1) = chr(&h0e)   ' fill
      else
         select case (mv - ((i - 1) * 4))
            case 0
               mid(Meter, i, 1) = chr(&h12)   ' empty
            case 1
               mid(Meter, i, 1) = chr(&h11)   ' 1/4
            case 2
               mid(Meter, i, 1) = chr(&h10)   ' 2/4
            case 3
               mid(Meter, i, 1) = chr(&h0f)   ' 3/4
            case else
               mid(Meter, i, 1) = chr(&h12)   ' empty
         end select
      end if
   next
   call ShowStringOnTV(Line, 0, chr(&h0D) & Meter & chr(&h13))
end sub



Tom
Back to top
pdubinsky



Joined: 25 Nov 2005
Posts: 66
Location: South Carolina

Posted: 02 January 2010, 19:17 PM    Post subject: Reply with quote

Tom,

Thanks a lot for the code. I got my circuit working (the Sparkfun MAX7456 breakout and a ZX24N) working with it. Three things:

1. The reset line on the breakout board needed a pullup (10k to +5V).

2. The ZX24N needed the pullup, too.

3. The compiler, at first, refused to compile your code citing line 24 as longer than 1,023 characters. That's the OSDCharTable table description. I took the comments off the ends of the lines and it compiled fine. That's weird, tho I haven't counted the characters in that line yet, I don't think that they add up to more than 1,023 characters.

Again, thanks and Happy New Year,
Paul
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR

Posted: 02 January 2010, 20:24 PM    Post subject: Reply with quote

pdubinsky wrote:
I took the comments off the ends of the lines and it compiled fine.
The problem can also be resolved by removing the underscore (line continuation) character. It isn't needed in body of the initialization because that construct is allowed to span multiple lines without explicit line continuation. For example, I would write the definition like this:
Code:
Dim OSDCharTable as ByteVectorData ({
  &h42,&h42,&h42,&h42,&h42,&h42,&h42,&h42,
  &h42,&h42,&hEA,&hEB,&hec,&hed,&hee,&hef,    ' =, degree...
  &hf0,&hf1,&hf2,&hf3,&hf4,&hf5,&hf6,&hf7,
  &hf8,&hf9,&hfa,&hfb,&hfc,&hfd,&hfe,&hff,
  &h00,&h42,&h48,&h42,&h42,&h42,&h42,&h46,    ' space - '
  &h3f,&h40,&h42,&h42,&h45,&h49,&h41,&h47,    ' ( - /
  &h0A,&h01,&h02,&h03,&h04,&h05,&h06,&h07,    ' 0 - 7
  &h08,&h09,&h44,&h43,&h4a,&h42,&h4b,&h42,    ' 8 - ?
  &h4c,&h0b,&h0c,&h0d,&h0e,&h0f,&h10,&h11,    ' @ - G
  &h12,&h13,&h14,&h15,&h16,&h17,&h18,&h19,    ' H - O
  &h1a,&h1b,&h1c,&h1d,&h1e,&h1f,&h20,&h21,    ' P - W   
  &h22,&h23,&h24,&h42,&h42,&h42,&h42,&h42,    ' X - _   
  &h42,&h25,&h26,&h27,&h28,&h29,&h2a,&h2b,    ' ` - g   
  &h2c,&h2d,&h2e,&h2f,&h30,&h31,&h32,&h33,    ' h - o   
  &h34,&h35,&h36,&h37,&h38,&h39,&h3a,&h3b,    ' p - w   
  &h3c,&h3d,&h3e,&h42,&h42,&h42,&h42,&h42     ' x - ~
})
Having the opening and closing sequences on a separate line makes it simpler to edit the data if necessary.
Back to top
GTBecker



Joined: 18 Jan 2006
Posts: 457
Location: Cape Coral

Posted: 02 January 2010, 23:02 PM    Post subject: Reply with quote

I forgot that the 7456 needed a Reset pullup, you're right.

I'm suprised that the -n needs one on /CS since it doesn't take code from the EEPROM. Did the lack of that pullup cause an SPI failure to the 7456 or a more comprehensive failure?
Back to top
pdubinsky



Joined: 25 Nov 2005
Posts: 66
Location: South Carolina

Posted: 03 January 2010, 1:35 AM    Post subject: Reply with quote

I was a 7456 failure. I had the /CS pin (pin 7 in my cirscuit) set at zxOutputHigh w/ I thought brought in the on board pullup. I looked at the MOSI line w/ a scope and it looked as though the logic high was just the DOC minimum of 2.0 volts so I got distracted by that and started trying pullups on the MOSI line to no avail. Later when added the external 10k pullup, it started working correctly. Actually, I was so blindsided by the pullup that I thought that the 7456 was fubarred.


BTW, the docs clearly show that the reset needs to be pulled high. I just missed it. My bad.

Paul
Back to top
GTBecker



Joined: 18 Jan 2006
Posts: 457
Location: Cape Coral

Posted: 03 January 2010, 3:56 AM    Post subject: Reply with quote

Ha! Dog eye tracking. http://www.ustream.tv/recorded/3707341
Back to top
twesthoff



Joined: 17 Mar 2006
Posts: 191
Location: Fredericksburg, VA

Posted: 03 January 2010, 4:57 AM    Post subject: Simple NTSC video object tracking, I think Reply with quote

When I click on the link the video doesn't show up.  Everything else on the page looks OK.  Is it just me?  I tried IE and Thunderbird with the same results.
Tom W.

On 1/2/2010 10:56 PM, General wrote:
Quote:
Ha! Dog eye tracking. http://www.ustream.tv/recorded/3707341



Tom




Back to top
GTBecker



Joined: 18 Jan 2006
Posts: 457
Location: Cape Coral

Posted: 03 January 2010, 5:13 AM    Post subject: Reply with quote

It works here, but a friend in Miami Beach had trouble for awhile, too. Try again. http://www.ustream.tv/recorded/3707341
Back to top
Display posts from previous:   
Post new topic   Reply to topic    Forum Index -> General Time synchro. with the server - Timezone/DST with your computer
Goto page 1, 2  Next
Page 1 of 2

 


All content Copyright © 2005-2012 Elba Corp. All Rights Reserved.
Opinions expressed in posts are those of the author and not necessarily those of Elba Corp.
Powered by phpBB © 2001, 2005 phpBB Group