please implement autofocus functions and algorithm...
Creado el: 12 de octubre de 2026
Respondido usando GPT-5.6 Thinking por Chat01
Creado el: 12 de octubre de 2026
Respondido usando GPT-5.6 Thinking por Chat01
please implement autofocus functions and algorithms to mainwindow, when i click on button
void MainWindow::on_pushButton_clicked()
{
// here apply algorithm to getting best light
}
start algorithm to changing LED and exposure to get best light depend on that algorithm
make non-blocking algorithm for UI qt, also you will find how to change LED and expsure from mainwindow and apply it
if missing any data or have any question ask
need full edited 4 files
I’ll wire the lighting optimizer into the existing MainWindow paths for LED (hardware->setRgb) and camera exposure, and make the button start an incremental frame-driven search so the GUI never blocks. I’m also checking how the current frame and button slot are handled so the edited files fit your existing code rather than assuming a second camera reader.
The key integration is clear: your preview frames already arrive in MainWindow::updateFrame, so I don’t need (and should not create) a second VideoCapture reader. I’m using those live frames as samples while the optimizer changes exposure through DetectionThread::set_camera_settings_Exposure() and red LED power through Hardware_Control::setRgb().
I found the existing button stub at the end of mainwindow.cpp. I’m also tracking the current exposure whenever MainWindow applies one, so cancellation/failure can restore both the previous exposure and LED instead of leaving the microscope at an arbitrary test setting. The optimizer’s scoring remains the supplied percentile/contrast/clipping algorithm.
The four-file implementation is now wired as an incremental state machine: each preview frame advances only one small part of the sweep, and settling is handled by ignoring frames until the delay expires rather than sleeping the Qt GUI thread. The coarse/fine LED search and median-over-multiple-frames scoring are preserved, including rollback and cancellation.
I also ran the optimizer core through a compile-time syntax check and a small mocked run: the incremental sweep completes, and the cancel path restores the original LED/exposure values. I’m doing a final diff/consistency pass on the MainWindow integration before packaging the four complete files.
Implemented the LED + exposure automatic lighting search into MainWindow::on_pushButton_clicked().
Your existing project already changes exposure through DetectionThread::set_camera_settings_Exposure() and LED through hardware->setRgb(...); the implementation uses those same paths. (mainwindow.cpp) (mainwindow.cpp) The supplied autofocus scoring algorithm is preserved: P5/P50/P95, contrast, brightness target, clipping, and dark-pixel penalties. (autofocus.cpp)
The important change is that I did not run findBestLighting() synchronously on the GUI thread, since the supplied code explicitly warns that would block Qt. (README.md) Instead, I added an incremental mode to Autofocus: every normal camera frame received by updateFrame() advances the search a little. No sleep(), no wait(), and no second camera reader.
Behavior now:
[Download mainwindow.cpp]
Or all four together:
Download all 4 edited files (.zip)
I syntax-tested the modified autofocus core and ran mocked completion/cancellation tests, including verifying rollback of the original LED and exposure. I couldn't perform a complete Qt application build because the full project/build files and the rest of its headers/libraries weren't supplied.
great work, instead of making best light, make it best light with besh focus, so please this button should get best lighting and best focus, here 2 motors to move to make best focus,
OBJ and CAM motors and try to move slow steps not much
make smart algorithm to do that to notice changing in light and in 2 stepper motors what it does
OBJ motor not accurate in accuracy so fix it first then start moving CAM motor.
I’ll extend the same non-blocking button workflow into two phases: first stabilize/optimize lighting, then optimize focus with OBJ first (to compensate for its lower repeatability) and CAM second using small, slow moves and live focus scores. I’ll keep every step event-driven so the UI stays responsive, and I’ll reuse your existing motor commands/position feedback rather than inventing a separate motor path.
I found a useful existing signal in your project: DetectionThread::focusScoreUpdated(double) already provides the sharpness metric, and both motor positions are already fed back through motorPositionReached. I’ll use that rather than duplicating image-focus code; for the less-accurate OBJ axis I’m adding one-direction scanning plus backlash take-up before each OBJ pass and before the final OBJ position, then CAM gets the smaller fine search.
The combined search will be a coordinate-descent sequence: Light → OBJ coarse → OBJ fine/backlash-corrected final → CAM coarse → CAM fine → light validation. If brightness has drifted significantly after focusing, it performs one re-light pass and then only a tiny CAM refinement, avoiding an endless light/focus loop.
The search logic is now coded with small ranges and robust scoring: each focus point waits for motor settle, collects 9 focus scores, trims two high/two low outliers, and compares the middle samples. OBJ never reverses direction while measuring; its final best position is also re-approached from below to reduce backlash/repeatability error.
The motor completion path is also made tolerant of your firmware behavior: it accepts either the dedicated motorPositionReached event or an idle motorStatusReceived update, but the handler is guarded so duplicate reports cannot advance the search twice. This matches the feedback architecture already present in MainWindow.
I kept the focus travel intentionally tight because your code doesn’t expose hard OBJ/CAM upper limits: OBJ searches only ±0.45 mm coarse then ±0.12 mm fine; CAM uses ±0.30 mm then ±0.075 mm. Lower travel is clamped at zero. If your firmware has explicit upper travel limits, those can be added later without changing the algorithm.
Implemented. The button now performs combined automatic lighting + two-motor focus, while staying non-blocking.
The sequence is:
MOVE_S.focusScoreUpdated(double) signal and rejects the two highest and two lowest samples before scoring. Your application already exposes this focus signal to MainWindow. (mainwindow.cpp)I kept the supplied Autofocus class responsible for the photometric stage, because that class was specifically designed for LED/exposure rather than Z-axis focusing. (autofocus.h) MainWindow now coordinates that stage with the motors and focus score. Exposure still goes through your existing camera-setting path, rather than a second camera controller. (mainwindow.cpp)
The algorithm is completely event-driven: motor feedback, QTimer settling, live camera frames, and focus-score signals. There are no sleeps or blocking loops in the GUI thread. It also accepts both your motor-position feedback path and idle motor-status feedback, because your existing application already maintains OBJ/CAM positions from hardware events. (mainwindow.cpp)
Download all 4 files — Auto Light + Focus ZIP
Individual files:
mainwindow.cpp
mainwindow.h
autofocus.cpp
autofocus.h
One hardware detail is still unknown from the files: I found no explicit maximum permitted OBJ/CAM positions, so I did not invent upper limits. The searches are intentionally very small around the current positions and clamp negative positions to zero. If your ESP32 firmware has known OBJ/CAM min/max travel values, give me those values and I can add hard safety limits around every autofocus move.
it work great but need improve that algorithm because sometimes it stops with bad score
first need get best lighting ( fast way not important to get it best now)
second start moving OBJ in range 0.1-1 mm depends on focus changes
third start getting best lighting
fourth start moving OBJ
and finally when close to getting best score like 50+
start using CAM to get best score
I’m updating the search into a staged light → OBJ → light → OBJ → CAM strategy. The main change is that OBJ step size will adapt from about 1.0 mm down toward 0.1 mm based on whether focus is improving, and CAM will only take over after OBJ has pushed the focus score into the “good” region around 50+.
A fixed OBJ window is the main weakness here: when focus is poor, a 0.15 mm step can be too small to escape it; when focus is already good, a large scan wastes time and can land on noise. I’m replacing that with a 1-D hill-climb: poor score uses larger OBJ jumps (up to 1 mm), improving score automatically shrinks the step, and near focus it works at 0.1 mm while always compensating OBJ backlash.
The revised decision point is now explicit: CAM is not allowed to start while OBJ focus is clearly poor. OBJ gets a second pass under the better lighting, plus one bounded recovery pass if it is still below the “near-focus” region; only then does CAM perform the precision search. Final OBJ and CAM positions are re-measured before the run is accepted, so a noisy scan peak cannot silently become the final result.
I tested the adaptive OBJ logic against several synthetic focus curves: from badly defocused starting points it uses the larger jumps to approach the peak, then automatically collapses to 0.1 mm around the maximum instead of blindly scanning a fixed window. The second pass usually becomes very short because the precise lighting makes the local focus comparison more reliable.
Done. I changed the algorithm to follow the staged behavior you described instead of doing one fixed OBJ scan.
The new sequence is:
I also kept the OBJ backlash compensation: every important OBJ target is approached consistently from below. OBJ travel is bounded to ±2.5 mm from its starting position, and individual adaptive movements never exceed 1 mm.
The algorithm also re-measures the final OBJ and CAM positions. If CAM lands badly compared with its measured optimum, it performs one extra fine CAM refinement instead of accepting the bad score. If the final score is still below 40, it rejects the result and restores the previous LED/exposure/OBJ/CAM settings rather than reporting bad focus as success.
Download all 4 files — adaptive light + focus
mainwindow.cpp
[mainwindow.h]
autofocus.cpp
[autofocus.h]
The main algorithm changes are in mainwindow.cpp and mainwindow.h; the two autofocus files are included so you still have the complete four-file set.
good progess, need more updates
1- first good getting best lighting fast way, but make sure its best lighting, because sometimes getting best lighting is dark screen
2- when moving OBJ for example 0-10 whiling moving focus in middle like in 6 getting best focus, but system continue to 10 and in 10 bad focus thats why, need watching focus while OBJ and CAM moving espically OBJ because it change focus big numbers
3- also while moving motors checking light if bad improve it in middle
I’ll tighten three things together: enforce a stronger “not dark” lighting acceptance rule, sample focus continuously while OBJ/CAM are actually moving so a peak around position 6 is remembered even if the motor later reaches 10, and allow mid-move lighting correction when brightness collapses. I’ll keep the same non-blocking Qt flow and return the full four edited files again.
I found the exact reason for the overshoot: OBJ’s “adaptive step” could still be sent as one long MOVE_S, so focus was only judged after the target was reached. I’m changing a 1.0 mm logical OBJ move into monitored ~0.10 mm physical segments; each segment is scored before the next one is sent, so if focus peaks partway through, the search stops advancing and returns to that peak instead of blindly reaching the original far target.
For lighting, I’m also changing the selector itself—not just adding a retry. A candidate that is nearly black will no longer be allowed to beat a properly illuminated candidate just because the dark image has strong contrast. The fast pass stays fast, but it now has hard usability limits and automatically performs one brighter rescue sweep only when those limits are not met.
The focus-search change is now structural rather than just tuning constants: a large OBJ request is treated as a logical search distance, not one blind motor command. The hardware advances in 0.10 mm monitored segments, keeps the best position seen, stops the logical move as soon as focus drops meaningfully after a peak, and later re-approaches the winning OBJ position with backlash compensation.
The live-light path is also connected now: preview frames are checked during focusing, but LED/exposure changes are deferred only until the current tiny motor segment ends. If several consecutive frames become too dark or clipped, focus pauses, lighting is repaired, and that focus stage restarts from the current motor position so scores from two different lighting conditions are never compared as if they were equivalent.
A sanity simulation of the new monitored OBJ behavior matches your example: for a logical 1.0 mm move with the true focus peak at 0.6 mm, it samples 0.1 mm increments, records the peak at 0.6, sees the drop at 0.7, and stops there instead of continuing blindly to 1.0. The same idea is used on your real focus-score signal, with CAM using its smaller native steps plus live peak hints.
The implementation pass is complete. The important behavioral changes are all in place: lighting can’t silently accept a black winner, OBJ long moves are broken into monitored 0.10 mm segments with peak-stop behavior, CAM can revisit a stronger focus seen between stops, and persistent bad lighting pauses/restarts the current focus stage under corrected illumination.
Updated. This version specifically addresses the three problems you described.
1. Fast lighting can no longer select a dark screen. The lighting algorithm now gives absolute priority to a usable image over a dark/high-contrast image. For this microscope workflow I set the minimum usable lighting to roughly:
The first lighting pass is still fast. If it cannot meet those limits, it automatically performs one brighter rescue search with more exposure/LED candidates before focusing begins.
2. OBJ no longer blindly moves past the best focus. A requested adaptive OBJ movement can still logically be 0.1–1.0 mm, but a large move is physically divided into approximately 0.10 mm monitored segments.
So instead of:
0 → 1 mm → measure
it effectively does:
0 → 0.1 → measure → 0.2 → measure → ...
If focus behaves like:
20 → 30 → 42 → 55 → 63 → 58 → 45
the system remembers 63, detects the decline immediately after it, and stops continuing farther away.
It then returns to that winning OBJ position using the backlash-compensated approach.
It also watches focusScoreUpdated() while the motor itself is moving. If it sees a significantly better focus between two stopped positions, that estimated position becomes a revisit target and is verified while stationary.
3. CAM now watches the peak too. CAM already uses much smaller steps, but it now also watches the live focus signal between positions. If a strong peak appears between two CAM stops, that intermediate location is inserted as the next verification point.
Once CAM has reached approximately 50+ and the focus starts dropping significantly, it stops scanning farther away and returns toward the best position.
4. Lighting is continuously checked during motor focusing. During OBJ and CAM movement, the preview is checked roughly every 180 ms. It requires several consecutive bad-light frames before reacting, so one strange frame will not interrupt autofocus.
If lighting becomes persistently:
the system marks a lighting repair as pending.
For OBJ, because movements are now only ~0.10 mm at a time, the repair occurs at the next tiny movement boundary. Then:
pause focus → repair LED/exposure → restart current focus stage
Importantly, it does not compare old focus scores against new scores after changing lighting, because that would make the focus comparison unreliable.
I also increased the minimum acceptable final focus from 40 to 45, while 50+ remains the preferred CAM region.
Individual files:
I also syntax-checked the modified autofocus.cpp with an OpenCV-compatible stub and tested the new monitored-movement logic against a synthetic focus curve. A full Qt application compile isn't possible here because the rest of your Qt project headers/libraries aren't available in the uploaded set.
good progess, but still that not what i want, it gives 50+, but need 90+, it can get it,
1- try move far more with OBJ and notice, if focus is inceasing good or not, maybe short area in 2 directions fast to see what directions is better then move far and looking at light and focus, and can improve lighting while moving OBJ and watching, i need 90+, so when get focus 90+ can see what OBJ position getting status or stop it and start moving it in low area
I’ll change the focus strategy from “stop once it is good enough” to “actively hunt for 90+.” OBJ will first probe both directions over a short distance, pick the better direction, then travel farther in monitored increments while continuously tracking focus and lighting; once it reaches 90+ (or clearly peaks), it will bracket that region and switch to smaller steps around the best OBJ position before handing off to CAM for final refinement.
I’ll make 90 the real target rather than a “nice-to-have.” The new OBJ strategy will do a quick directional probe on both sides first, then follow the winning slope over a much larger bounded distance while sampling every small segment; once it sees 90+, it stops the long-range climb immediately and switches to a tight local OBJ search around that position. CAM then becomes the final precision stage rather than the mechanism that has to rescue a mediocre OBJ result.
I’m also making the “far move” safe by separating logical distance from physical motor commands: the algorithm may decide “continue 2 mm in this direction,” but it never sends a blind 2 mm move. It sends monitored slices—about 0.15 mm when badly defocused, 0.08 mm near focus, and 0.05 mm once the score is around 85—so a 90+ peak is localized instead of crossed.
I’m tightening the live-light behavior too. During the OBJ hunt, lighting is checked more aggressively; if it becomes persistently dark/clipped, the focus climb pauses at the next tiny segment boundary, relights, and restarts the local comparison from the current position. That avoids comparing focus scores measured under two different illumination conditions.
The 90+ target logic is now in place. If a moving OBJ segment sees 90+ before the commanded endpoint, that live peak is saved as a hint and revisited immediately for a stationary measurement; after verification, the algorithm switches from long-range travel to a tight OBJ bracket instead of continuing the far sweep.
A synthetic focus-curve check now finds the intended behavior: the short two-direction probe identifies the rising side, the long logical OBJ climb advances in monitored slices, and the search switches into the fine region as soon as the curve crosses 90 instead of continuing toward the far endpoint. I’m doing the final consistency pass and packaging the four files.
Updated. This version is much more aggressive about finding 90+ focus rather than accepting 50–70.
The OBJ strategy is now:
Lighting monitoring is also faster now. During OBJ/CAM search it checks illumination more frequently; after two consecutive bad-light checks it pauses focus at the next small motor boundary, quickly recalibrates LED/exposure, and restarts that local focus stage. That prevents focus measurements under bad lighting from corrupting the search.
I also changed the final target logic: 90 is now the actual target. If CAM finishes below 90, it performs additional CAM brackets. If those still fail, it allows one more expanded OBJ recovery search before accepting the best stable result.
Because your uploaded code still doesn't expose a hard maximum OBJ travel limit, I bounded the new expanded search to ±6 mm from the OBJ position at button click. If you know the real minimum/maximum OBJ positions, send them to me and I strongly recommend replacing this relative safety bound with the actual hardware limits.
great work but still OBJ is moving even if in middle moving found a high score, so i added 2 commands to use them only to control OBJ and CAM
1- move_t OBJ +/- speed ( steps/second) to keep moving motor till find best focus and send stop_motors
2- stop_motors to stop motor
3- 150 for slow speed that when focus is good but need a little improvement, 1000 speed is used for start making focus and see what best position to stop OBJ
3- you moving CAM a little, it can move more much to improve focus use that too
4- lighting is good dont change it.
I’ll keep the lighting stage exactly as it is and change only the motor-focus behavior. OBJ/CAM will use your new continuous commands (move_t ... / stop_motors) so the software can stop immediately when the live focus score peaks, instead of waiting for a precomputed position move to finish.
I found the key simplification: with move_t, I no longer need to predict a distant OBJ endpoint at all. I’ll let OBJ move continuously at 1000 steps/s during the direction hunt, stop it immediately from the live focusScoreUpdated path when a strong peak/decline is detected, then restart at 150 steps/s around that region for fine improvement; CAM will use the same continuous-stop idea and will be allowed substantially more travel than before.
The implementation will now treat move_t as a live search rather than a move-to-position command. At 1000 steps/s it will hunt quickly; once it detects the peak region it sends stop_motors immediately, asks for motor status, then resumes that axis at 150 steps/s for fine peak tracking. CAM gets the same mechanism with a much wider allowed search range than before.
The new stop behavior is wired now: high focus is handled inside the live focusScoreUpdated() callback, so stop_motors is sent while the continuous command is still running—there is no wait for a distant OBJ/CAM target anymore. After stopping, the code requests STATUS, uses that stopped position, and the 150-step/s pass searches locally around the detected peak.
I kept the lighting code unchanged in this revision. During the new continuous focus hunt, it also no longer launches the mid-focus relighting routine, so LED/exposure stay fixed while OBJ/CAM are being compared—this keeps the live focus scores directly comparable.
Updated exactly around your new motor commands.
The lighting algorithm is unchanged. After lighting is set, focus now uses only continuous motion logic for the new autofocus path:
move_t OBJ + 1000 / move_t OBJ - 1000 for fast OBJ hunting.focusScoreUpdated() is watched while OBJ is moving.stop_motors.STATUS to get the stopped OBJ position.+ and - directions before committing to the better direction.CAM now works similarly and has much more freedom than before:
+/- direction probe.stop_motors on 90+ / detected peak.Importantly, the motor no longer has to finish a distant move before the software reacts. For example, if OBJ is moving and focus goes 40 → 55 → 72 → 91, the software sends stop_motors at the high-focus region instead of continuing to the old endpoint.
Lighting is kept fixed during this continuous OBJ/CAM search so changing exposure/LED does not distort the focus comparison.
Download all 4 files — continuous stop autofocus
autofocus.cpp/.h are intentionally unchanged from the previous working lighting version; the new continuous OBJ/CAM behavior is implemented in mainwindow.cpp/.h.