Lapser Script Development - page 3 - LUA Scripting - CHDK Forum supplierdeeply

Lapser Script Development

  • 50 Replies
  • 19933 Views
*

Offline reyalp

  • ******
  • 14080
Re: Lapser Script Development
« Reply #20 on: 12 / July / 2017, 17:48:41 »
Advertisements
Requiring the script to do the timing, though, is like locking me up in a tiny half bathroom of a 20,000 square foot mansion. Let me out!
This seems like a misunderstanding. There is only so much time between shots, and if the script takes longer than that to execute, the interval won't be maintained.

If your script gets to hook_shoot.wait_ready() after the hook is ready, it will just continue next part (in rawopint, the sleep calculation). As long as it gets there before continue to needs to be called, the interval can still be maintained.

In any case, if your Lua code is taking a significant fraction of a second to execute (outside of the actual raw buffer processing that happens in the raw hook), there's probably something wrong with it.
Don't forget what the H stands for.

*

Offline c_joerg

  • *****
  • 1248
Re: Lapser Script Development
« Reply #21 on: 16 / July / 2017, 09:13:56 »
Are any of them available in 64 bit?


I haven’t found 32 bit version for deflicker. I Have a 32 and 64 bit version of VirtualDub.
But I never had limitations with the 32 bit version.
M100 100a, M3 121a, G9x II (1.00c), 2*G1x (101a,100e), S110 (103a), SX50 (100c), SX230 (101a), S45,
Flickr https://www.flickr.com/photos/136329431@N06/albums
YouTube https://www.youtube.com/channel/UCrTH0tHy9OYTVDzWIvXEMlw/videos?shelf_id=0&view=0&sort=dd

*

Offline lapser

  • *****
  • 1093
Re: Lapser Script Development
« Reply #22 on: 06 / September / 2017, 17:46:24 »
I'm finally finished processing my eclipse photos, so I'm back to CHDK programming.

First of all, the total eclipse was incredible! If you get a chance to see one, do it. I was able to use a script I wrote to take photos of the eclipse with the EOS-M3 connected to a nice 80mm APO refractor.

I wrote the script so that I could change the shot interval and exposure with the arrow keys. The set key switched between bracket mode, for totality, and fixed exposure mode, for the partial phases. I took the solar filter off, and switched to bracket mode, when the last hint of the bright Sun was gone.

During totality, the script added 10 ev of exposure, then reduced exposure by 1ev until the brightest pixel was 1 ev below white level (1/2 of white level linear). To do this, I had to break my vow of Lua only, and compile a version with rawop_meter() modified to also return the 2nd brightest and brightest pixel values, and the number of blown(white level) pixels, in addition to the mean value. The Lua call looks like this:

mean,pmax2,nwhite,pmax1=rawop.meter(mx1,my1,mxcount,mycount,mxystep,mxystep)
 
I also modified rawop.meter to handle the overflow problem when computing the mean with a large number of pixels. I'll post the changes I did soon, and hopefully they'll end up in the trunk.

I had some trouble debugging the eclipse script because of having to handle hook_shoot and hook_raw. So after I got back, I added an interval timer to script_shoot_hook_run(timeout). A negative timeout is treated as an interval. A -1 timeout disables the timeout so the script has to call continue() to exit the hook. I also return the hook enter and exit tick times with the count. Here's what it looks like in Lua.

hook_raw.set(-1) -- no timeout
hook_shoot.set(-interval) -- allows changing interval between shots
count,henter,hexit=hook_shoot.count() -- hook enter and exit times also returned

I have both changes working with test scripts. I'll post something after I clean the code up and test it a little more.

Here's the time lapse of the entire eclipse that I put together:


A sample of photos of totality is here:
https://www.facebook.com/media/set/?set=a.1999495843615337.1073741829.1568184233413169&type=1&l=140192468c

For a full hi-res HDR photo, made from 8 individual photos during totality, click here:
https://secure.meetupstatic.com/photos/event/5/a/c/8/highres_464303240.jpeg
EOS-M3_120f / SX50_100b / SX260_101a / G1X_100g / D20_100b
https://www.youtube.com/user/DrLapser/videos

*

Offline c_joerg

  • *****
  • 1248
Re: Lapser Script Development
« Reply #23 on: 07 / September / 2017, 02:42:33 »
It really is absolutely great what you did there. I am really impressed.  :)
You cannot paint at all when clouds were raised ...

then reduced exposure by 1ev until

Do you think it’s necessary to do it in 1ev steps if using RAW.  Would be interesting to know, how the picture looks like if you use only every second picture…

Did you operate your M3 in continuous Mode? I read in the M3 manual, that the continuous Mode is limited to 1000 shoots. Did you ever come to this limit? My longest run was 970 shoots on M3…

Have you ever notice these lines on your M3?
https://www.dpreview.com/forums/thread/4006320

I've read that it just happens in astro photography and stacking. In my M3 is not noticeable to me yet but i never did astro photography and stacking.

M100 100a, M3 121a, G9x II (1.00c), 2*G1x (101a,100e), S110 (103a), SX50 (100c), SX230 (101a), S45,
Flickr https://www.flickr.com/photos/136329431@N06/albums
YouTube https://www.youtube.com/channel/UCrTH0tHy9OYTVDzWIvXEMlw/videos?shelf_id=0&view=0&sort=dd


*

Offline lapser

  • *****
  • 1093
Re: Lapser Script Development
« Reply #24 on: 07 / September / 2017, 10:43:35 »

then reduced exposure by 1ev until
Do you think it’s necessary to do it in 1ev steps if using RAW.  Would be interesting to know, how the picture looks like if you use only every second picture…
Yes, I thought about using 2 or 3 ev steps, but with a <1 second interval I knew I could get at least 6 complete cycles during totality. You don't get a lot of testing time with a 90 second event that happens once in a lifetime!
Did you operate your M3 in continuous Mode? I read in the M3 manual, that the continuous Mode is limited to 1000 shoots. Did you ever come to this limit? My longest run was 970 shoots on M3…
YES!!! Thanks!!!!! I spent hours trying to figure out why the camera stopped after it got over 800 or 900 shots, assuming it was in my script. The script must have hung waiting for one of the hooks. I turned the power off and back on during the eclipse, but I could have pressed the shutter button to exit the script. I might have saved my log file if I did that.

I noticed this without CHDK. On the EOS-M, you can click the remote in continuous mode and it keeps taking pictures forever. I've used this to take overnight time lapses with long exposures. It works on the M3, but it stopped after <1,000 pictures.

I'll experiment to see if release("shoot_full_only") prevents this. Or maybe just press("shoot_full_only") after every shot would work. Better yet, maybe one of the hackers can figure out how to disable it?
Have you ever notice these lines on your M3?
https://www.dpreview.com/forums/thread/4006320

I've read that it just happens in astro photography and stacking. In my M3 is not noticeable to me yet but i never did astro photography and stacking.
Thanks for that link. I haven't noticed lines, but I haven't looked closely. I use Lightroom to process raw files, which apparently somewhat corrects the problem.

Stacking software lets you input "flat frames." Those are photos taken of a uniformly light gray scene, like empty sky. I think the lines would show up, and be corrected by using a lot of flat frames. I've done some stacking, but I prefer to use single frames.

Thanks again for all the great info!
EOS-M3_120f / SX50_100b / SX260_101a / G1X_100g / D20_100b
https://www.youtube.com/user/DrLapser/videos

*

Offline lapser

  • *****
  • 1093
Re: Lapser Script Development - rawop_meter() enhancements
« Reply #25 on: 07 / September / 2017, 22:21:34 »

Here's the enhancements to rawop_meter I mentioned, along with a test script.
Code: [Select]
static int rawop_meter(lua_State *L) {
    if(!raw_buffer_valid) {
        return luaL_error(L,"raw data not available");
    }
    unsigned x1=luaL_checknumber(L,1);
    unsigned y1=luaL_checknumber(L,2);
    unsigned x_count=luaL_checknumber(L,3);
    unsigned y_count=luaL_checknumber(L,4);
    unsigned x_step=luaL_checknumber(L,5);
    unsigned y_step=luaL_checknumber(L,6);


    // no pixels
    if(!x_count || !y_count) {
        return 0;
    }


    unsigned x_max = x1 + x_step * x_count;
    unsigned y_max = y1 + y_step * y_count;
    // x out of range
    if(x_max > (unsigned)camera_sensor.raw_rowpix) {
        return 0;
    }
    // y out of range
    if(y_max > (unsigned)camera_sensor.raw_rows) {
        return 0;
    }
//lapser - max value is 2^63 now, so overflow check not needed
    // overflow possible (int max)/total  < max value
//    if(x_count*y_count > (unsigned)0xFFFFFFFF >> camera_sensor.bits_per_pixel) {
//        return 0;
//    }
    unsigned x,y;
   int t=0; //int detects overflow into sign bit when t<0 (lapser)
    unsigned t1=0; //overflow counter
   unsigned p,pmax1=0,pmax2=0,nwhite=0; //lapser variables for ETTR use
    for(y = y1; y < y_max; y += y_step) {
        for(x = x1; x < x_max; x += x_step) {
         //t+=get_raw_pixel(x,y);
         p=get_raw_pixel(x,y); //lapser
         
         //set_raw_pixel(x,y,(short)camera_sensor.white_level); //*****TEST*****


         if(p>=pmax2) { //must use >=, not >, for nwhite counting
            if(p>=camera_sensor.white_level)nwhite++;
            if(p>pmax1) { //finds brightest and 2nd brightest pixels for ETTR
               pmax2=pmax1;
               pmax1=p;
            }
            else pmax2=p;
         }
            t+=p;
         if(t<0){ //handles overflow
            t1++;
            t &= 0x7FFFFFFF;
         }
        }
    }
   x=x_count*y_count;
   y = ((unsigned)t | (t1<<31)); //can use unsigned bit 31 now
   t1 >>= 1; // [t1,y] is now a 64 bit integer
   while(t1!=0){
      y = (y>>1) | (t1<<31); // 64 bit right shift >> 1
      t1 >>= 1;
      x >>= 1; //shift denominator so y/x value is unchanged
   }
    lua_pushnumber(L,y/x);
    lua_pushnumber(L,pmax2); //lapser
    lua_pushnumber(L,nwhite); //lapser
    lua_pushnumber(L,pmax1); //lapser


    //return 1;
   return 4; //lapser
}
And here's a script to test them with:
Code: [Select]
--[[
@title Lapser Rawop Test
@chdk_version 1.5.0
#nshots=4 "# Shots (0: no limit)"
#otest=false "Overflow Test?"
]]


--logger s: one line sent to log file (set fname before first call)
bi=get_buildinfo()
fname="A/CHDK/LOGS/"..bi.platform..os.date("_%y%m%d_%H%M_TestRwop.log")
function logger(s)
  if slog==nil then -- first call opens file
    if s==nil then return end -- don't open empty file
    flog=io.open(fname,"ab")
    slog={}
    nlog=0
  end
  if s~=nil then
    nlog=nlog+1
    slog[nlog]=s
  else
    for i=1,nlog do
      flog:write(slog[i],"\n")
    end
    flog:close()
    slog=nil
  end
end


function ksleep(t)
  wait_click(t)
  if is_key("menu") or is_pressed("menu") then done=true end
end


function mparms(maxsteps,px1,py1,px2,py2)
  logger(string.format("maxsteps=%d,px1=%d,py1=%d,px2=%d,py2=%d",maxsteps,px1,py1,px2,py2 ))
  local jwh=rawop.get_jpeg_width()
  local jlt=rawop.get_jpeg_left()
  px1=jlt+((px1*jwh)/100)
  px2=jlt+((px2*jwh)/100)-px1 -- px2 is width now
  jwh=rawop.get_jpeg_height()
  jlt=rawop.get_jpeg_top()
  py1=jlt+((py1*jwh)/100)
  py2=jlt+((py2*jwh)/100)-py1 -- py2 is height now


  logger(string.format("x=%d,y=%d,w=%d,h=%d",px1,py1,px2,py2 ))


  local step=1
  while(px2*py2)/(step*step)>maxsteps do step=step+2 end
  local xsteps=px2/step + 1
  local ysteps=py2/step + 1
  px1=px1+((px2%step)/2) -- center sampled area
  py1=py1+((py2%step)/2)
  logger(string.format("x=%d,y=%d,xsteps=%d,ysteps=%d,step=%d",
    px1,py1,xsteps,ysteps,step))
  return px1,py1,xsteps,ysteps,step
end


--bi=get_buildinfo()
logger("TestRwop "..os.date())
logger(string.format("Camera:%s f/w:%s platformID:%s bit/pixel:%d",
  bi.platform,bi.platsub,bi.platformid,rawop.get_bits_per_pixel()))
logger(string.format("version:%s %s built on %s %s",
  bi.version,bi.build_number,bi.build_date,bi.build_time))




logger(string.format("Nshots=%d",nshots))


cls()
--set_console_autoredraw(-1)
set_draw_title_line(0)
osd=get_config_value(1)
set_config_value(1, 0)
done=false
hook_raw.set(10000000)


if otest then msteps=24000000 else msteps=24000 end -- overflow test?


mx1,my1,mxcount,mycount,mxystep=mparms(msteps,0,0,100,100)
nsteps=mxcount*mycount


white=rawop.get_white_level()
logger(string.format("nsteps=%d white=%d",nsteps,white))


logger("Shot#  Mean Pmax2 Pmax1 Wh% Wh#")
logger() -- write log so far
press("shoot_half")
repeat sleep(10) until get_shooting()
press("shoot_full_only")
ishots=0




repeat
  while not hook_raw.is_ready() do ksleep(10) end
  ishots=ishots+1
  mean,pmax2,nwhite,pmax1=rawop.meter(mx1,my1,mxcount,mycount,mxystep,mxystep)
  logger(string.format("%5d%6d%6d%6d%3d%% %d",
    ishots,mean,pmax2,pmax1,(nwhite*100)/nsteps, nwhite))


  if done or ishots==nshots then
    release("shoot_full")
    done=true
  end
  hook_raw.continue()
until done
logger() -- print log and close file
set_config_value(1,osd)
To compile a test build, just put the attached rawhookops.c in the modules folder, replacing the one that's already there.


To run the test script, also attached, put the camera in continuous mode first, set the parameter for the number of shots you want, and if you want to do an overflow test. The overflow test sets the step size to 1, so it takes awhile between shots. For overflow testing, you can use manual exposure, 1 second, ISO 128000 to get a mostly white image.


The script creates a log file that looks like this (with overflow testing)
Code: [Select]
TestRwop Thu Sep  7 16:05:22 2017
Camera:g1x f/w:100g platformID:12851 bit/pixel:14
version:CHDK 1.5.0 built on Sep  7 2017 15:51:16
Nshots=0
maxsteps=24000000,px1=0,py1=0,px2=100,py2=100
x=108,y=76,w=4352,h=3264
x=108,y=76,xsteps=4353,ysteps=3265,step=1
nsteps=14212545 white=16383
Shot#  Mean Pmax2 Pmax1 Wh% Wh#
    1 16382 16383 16383 99% 14207056
    2 16382 16383 16383 99% 14206049
    3 12118 16383 16383 34% 4852188
    4 12008 16383 16383 34% 4939794
    5 11400 16383 16383 27% 3936243
    6 10838 16383 16383 25% 3610153
    7 10994 16383 16383 31% 4544427
Press and hold the menu button to exit the program (or set the number of shots>0)
[EDIT] I updated the attached TestRwop.lua to work with the EOS-M3
« Last Edit: 08 / September / 2017, 18:07:38 by lapser »
EOS-M3_120f / SX50_100b / SX260_101a / G1X_100g / D20_100b
https://www.youtube.com/user/DrLapser/videos

*

Offline lapser

  • *****
  • 1093
Re: Lapser Script Development - rawop_meter() enhancements
« Reply #26 on: 07 / September / 2017, 22:44:29 »
I've attached a build for the EOS-M3, 101a for c_joerg to use for testing.

I came up with the idea to include a test for the brightest and second brightest pixels in the mean calculation from my experience with my original time lapse script. In that script, I computed the full histogram and added the option to use the nth brightest pixel for ETTR histogram metering.

However, I soon discovered that the 2nd brightest pixel was the best one to use. The brightest pixel varies too much, and going higher than the 2nd just starts blowing out more and more pixels.

Before my eclipse trip, I added the code to return the additional info from rawop_meter. The lua call looks like this:
Code: [Select]
mean,pmax2,nwhite,pmax1=rawop.meter(mx1,my1,mxcount,mycount,mxystep,mxystep)
This week, I added the code to use a 2 variable, 63 bit accumulator to add up the pixels for the metering mean calculation.
Code: [Select]
    int t=0; //int detects overflow into sign bit when t<0 (lapser)
    unsigned t1=0; //overflow counter
//and in the loop
   p=get_raw_pixel(x,y); //lapser

   t+=p;
   if(t<0){ //handles overflow
      t1++;
      t &= 0x7FFFFFFF;
   }
I'm hoping reyalp will want to add this to the trunk. If not, I'll continue using my own builds as before.
EOS-M3_120f / SX50_100b / SX260_101a / G1X_100g / D20_100b
https://www.youtube.com/user/DrLapser/videos

Lapser Script Development
« Reply #27 on: 07 / September / 2017, 23:07:11 »
I'm curious. Would the third brightest pixel work as well? Or differently?

Somehow I worry about having one or more hot pixels out of millions throwing things off.  Maybe a user choice of the "n"th brightest pixel?. Or the average of the top "n"?
Ported :   A1200    SD940   G10    Powershot N    G16


*

Offline lapser

  • *****
  • 1093
Re: Lapser Script Development
« Reply #28 on: 07 / September / 2017, 23:56:43 »
I'm curious. Would the third brightest pixel work as well? Or differently?

Somehow I worry about having one or more hot pixels out of millions throwing things off.  Maybe a user choice of the "n"th brightest pixel?. Or the average of the top "n"?
That's a good question, but I've answered it with over 500 time lapses using the 2nd brightest and it works great. I tried 3rd, 4th, 10th, 100th pixels etc. and none of them worked as well.

Remember, you're sampling a small fraction of the pixels, if you want  rawop_meter to finish in a reasonable time. The odds of hitting 2 stuck hot pixels are low. It's never happened in all my time lapses.

That said, there's a lot of variation in the 2nd brightest pixel during a time lapse, especially at night with city lights in the frame. You can't use the value directly, or you'll get a lot of flashing.

I settled on an algorithm where I use the 2nd brightest pixel to slowly adjust the exposure. If it's above 50% linear (1 ev less than saturated) I reduce the exposure by around 1.5 to 2 ev96 (and I smooth that reduction too). If the pixel is darker than 50%, I increase the exposure by 1.5 ev or so (set by a script parameter). I also have a parameter for the maximum amount the pixel metering can reduce the exposure below the mean value. That's useful when the Sun or Moon is in the frame to keep everything else from getting too dark.

The advantage of using the 2nd brightest pixel is that you can compute its value in rawop_meter() with very little overhead (one "if" test). Using the nth pixel requires the full histogram, which has a very high overhead in memory and CPU time, not to mention it's more complicated to program. I did it that way in my original script, but I always set it to 2nd brightest, even though I could use any pixel.
EOS-M3_120f / SX50_100b / SX260_101a / G1X_100g / D20_100b
https://www.youtube.com/user/DrLapser/videos

*

Offline c_joerg

  • *****
  • 1248
Re: Lapser Script Development
« Reply #29 on: 08 / September / 2017, 12:28:29 »
I haven't noticed lines, but I haven't looked closely. I use Lightroom to process raw files, which apparently somewhat corrects the problem.
If I understand correctly, Canons DPP should handle it better because there know about the problem…
But I could not see the lines in my sensor.
Here's the enhancements to rawop_meter I mentioned, along with a test script.
 
Test script crashed on my M3. Picture attached.
I missed this in the script
Code: [Select]
require'hookutil'
require'rawoplib'
I still have problems to understand the meaning of second 2nd brightest pixel.
I know how to compute a histogram and the meaning of the individual cells. So I got a number how many pixels are in a particular range.
So, you are really talking about a pixel which is just one step below white?  So in worse case it could be just one pixel or? So, you don’t use a histogram?
nsteps=14212545 white=16383
Shot#  Mean Pmax2 Pmax1 Wh% Wh#
    1 16382 16383 16383 99% 14207056
    2 16382 16383 16383 99% 14206049
I would expect that Pmax would below white….
I'm hoping reyalp will want to add this to the trunk. If not, I'll continue using my own builds as before.

If I understand correctly, the interface of a function changes. Does that mean all other function calls in scripts has to be changed as well?
Would be interesting to see when I would log them in rawopint as well…
M100 100a, M3 121a, G9x II (1.00c), 2*G1x (101a,100e), S110 (103a), SX50 (100c), SX230 (101a), S45,
Flickr https://www.flickr.com/photos/136329431@N06/albums
YouTube https://www.youtube.com/channel/UCrTH0tHy9OYTVDzWIvXEMlw/videos?shelf_id=0&view=0&sort=dd

 

Related Topics