Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support crop image on sensor, grayscale, and auto exposure level #2799

Merged
merged 9 commits into from
Feb 10, 2024
337 changes: 262 additions & 75 deletions code/components/jomjol_controlcamera/ClassControllCamera.cpp

Large diffs are not rendered by default.

25 changes: 21 additions & 4 deletions code/components/jomjol_controlcamera/ClassControllCamera.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class CCamera {
protected:
int ActualQuality;
framesize_t ActualResolution;
int brightness, contrast, saturation;
int brightness, contrast, saturation, autoExposureLevel;
bool isFixedExposure;
int waitbeforepicture_org;
int led_intensity = 4095;
Expand All @@ -31,8 +31,24 @@ class CCamera {
bool loadNextDemoImage(camera_fb_t *fb);
long GetFileSize(std::string filename);

void SetCamWindow(sensor_t *s, int resolution, int xOffset, int yOffset, int xLength, int yLength);
void SetImageWidthHeightFromResolution(framesize_t resol);

public:
int image_height, image_width;
bool imageZoomEnabled = false;
int imageZoomMode = 0;
int imageZoomOffsetX = 0;
int imageZoomOffsetY = 0;
bool imageNegative = false;
bool imageAec2 = false;
bool imageAutoSharpness = false;
int imageSharpnessLevel = 0;
#ifdef GRAYSCALE_AS_DEFAULT
bool imageGrayscale = true;
#else
bool imageGrayscale = false;
#endif

CCamera();
esp_err_t InitCam();
Expand All @@ -41,9 +57,10 @@ class CCamera {
void LEDOnOff(bool status);
esp_err_t CaptureToHTTP(httpd_req_t *req, int delay = 0);
esp_err_t CaptureToStream(httpd_req_t *req, bool FlashlightOn);
void SetQualitySize(int qual, framesize_t resol);
bool SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation);
void GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol);
void SetQualitySize(int qual, framesize_t resol, bool zoomEnabled, int zoomMode, int zoomOffsetX, int zoomOffsetY);
bool SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation, int _autoExposureLevel, bool _grayscale, bool _negative, bool _aec2, int _sharpnessLevel);
void SetZoom(bool zoomEnabled, int zoomMode, int zoomOffsetX, int zoomOffsetY);
void GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol, bool &zoomEnabled, int &zoomMode, int &zoomOffsetX, int &zoomOffsetY);
void SetLEDIntensity(float _intrel);
bool testCamera(void);
void EnableAutoExposure(int flash_duration);
Expand Down
124 changes: 124 additions & 0 deletions code/components/jomjol_controlcamera/ov2640_sharpness.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#include <stdint.h>
#include "esp_camera.h"
#include "ov2640_sharpness.h"


#define OV2640_MAXLEVEL_SHARPNESS 6

const static uint8_t OV2640_SHARPNESS_AUTO[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0x20, 0x20,
0x00, 0x00, 0x00
};

const static uint8_t OV2640_SHARPNESS_MANUAL[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0x00, 0x20,
0x00, 0x00, 0x00
};

const static uint8_t OV2640_SHARPNESS_LEVEL0[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xc0, 0x1f,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL1[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xc1, 0x1f,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL2[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xc2, 0x1f,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL3[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xc4, 0x1f,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL4[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xc8, 0x1f,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL5[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xd0, 0x1f,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL6[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xdf, 0x1f,
0x00, 0x00, 0x00
};

const static uint8_t *OV2640_SETTING_SHARPNESS[]=
{
OV2640_SHARPNESS_LEVEL0, // -3 sharpness
OV2640_SHARPNESS_LEVEL1,
OV2640_SHARPNESS_LEVEL2,
OV2640_SHARPNESS_LEVEL3,
OV2640_SHARPNESS_LEVEL4,
OV2640_SHARPNESS_LEVEL5,
OV2640_SHARPNESS_LEVEL6 // +3 sharpness
};

static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
{
uint8_t address;
uint8_t value;
uint8_t orgval;
uint8_t mask;
const uint8_t *pdata = ptab;

if (pdata == NULL)
return -1;

while (1)
{
address = *pdata++;
value = *pdata++;
mask = *pdata++;
if ((address == 0) && (value == 0) && (mask == 0))
break;
sensor->set_reg(sensor, address, mask, value);
}

return 0;
}

int ov2640_enable_auto_sharpness(sensor_t *sensor)
{
table_mask_write(sensor, OV2640_SHARPNESS_AUTO);
return 0;
}


int ov2640_set_sharpness(sensor_t *sensor, int sharpness)
{
if ((sharpness < -3) || (sharpness > OV2640_MAXLEVEL_SHARPNESS - 3))
return -1;

table_mask_write(sensor, OV2640_SHARPNESS_MANUAL);
table_mask_write(sensor, OV2640_SETTING_SHARPNESS[sharpness + 3]);
return 0;
}
11 changes: 11 additions & 0 deletions code/components/jomjol_controlcamera/ov2640_sharpness.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#ifndef OV2640_SHARPNESS_H
#define OV2640_SHARPNESS_H

#include "esp_camera.h"

int ov2640_enable_auto_sharpness(sensor_t *sensor);
int ov2640_set_sharpness(sensor_t *sensor, int sharpness); // -3 to +3, -4 for auto-sharpness

#endif
28 changes: 20 additions & 8 deletions code/components/jomjol_controlcamera/server_camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,18 @@ esp_err_t handler_capture(httpd_req_t *req)
{
int quality;
framesize_t res;
bool zoomEnabled;
int zoomMode;
int zoomOffsetX;
int zoomOffsetY;

Camera.GetCameraParameter(req, quality, res);
Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);

#ifdef DEBUG_DETAIL_ON
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
#endif

Camera.SetQualitySize(quality, res);
Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);

esp_err_t result;
result = Camera.CaptureToHTTP(req);
Expand Down Expand Up @@ -136,6 +140,10 @@ esp_err_t handler_capture_with_light(httpd_req_t *req)

int quality;
framesize_t res;
bool zoomEnabled;
int zoomMode;
int zoomOffsetX;
int zoomOffsetY;
int delay = 2500;

if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
Expand All @@ -153,13 +161,13 @@ esp_err_t handler_capture_with_light(httpd_req_t *req)
}
}

Camera.GetCameraParameter(req, quality, res);
Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);

#ifdef DEBUG_DETAIL_ON
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
#endif

Camera.SetQualitySize(quality, res);
Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
Camera.LightOnOff(true);
const TickType_t xDelay = delay / portTICK_PERIOD_MS;
vTaskDelay( xDelay );
Expand Down Expand Up @@ -200,6 +208,10 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)

int quality;
framesize_t res;
bool zoomEnabled;
int zoomMode;
int zoomOffsetX;
int zoomOffsetY;

if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
{
Expand Down Expand Up @@ -228,11 +240,11 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
else
fn.append("noname.jpg");

Camera.GetCameraParameter(req, quality, res);
Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
#endif
Camera.SetQualitySize(quality, res);
Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);

esp_err_t result;
result = Camera.CaptureToFile(fn, delay);
Expand Down
2 changes: 1 addition & 1 deletion code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void ClassFlowAlignment::SetInitialParameter(void)
AlignAndCutImage = NULL;
ImageBasis = NULL;
ImageTMP = NULL;
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
AlgROI = (ImageData*)malloc_psram_heap(std::string(TAG) + "->AlgROI", sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
#endif
previousElement = NULL;
Expand Down
59 changes: 57 additions & 2 deletions code/components/jomjol_flowcontroll/ClassFlowTakeImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ void ClassFlowTakeImage::SetInitialParameter(void)
ImageQuality = 5;
rawImage = NULL;
ImageSize = FRAMESIZE_VGA;
ZoomEnabled = false;
ZoomMode = 0;
zoomOffsetX = 0;
zoomOffsetY = 0;
ImageNegative = false;
ImageAec2 = false;
#ifdef GRAYSCALE_AS_DEFAULT
ImageGrayscale = true;
#else
ImageGrayscale = false;
#endif
SaveAllFiles = false;
disabled = false;
FixedExposure = false;
Expand All @@ -73,6 +84,8 @@ bool ClassFlowTakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
int _brightness = -100;
int _contrast = -100;
int _saturation = -100;
int _sharpness = 0;
int _autoExposureLevel = 0;

if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
Expand All @@ -92,6 +105,43 @@ bool ClassFlowTakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
if ((toUpper(splitted[0]) == "IMAGEQUALITY") && (splitted.size() > 1))
ImageQuality = std::stod(splitted[1]);

if ((toUpper(splitted[0]) == "ZOOM") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
ZoomEnabled = true;
else if (toUpper(splitted[1]) == "FALSE")
ZoomEnabled = false;
}
if ((toUpper(splitted[0]) == "ZOOMMODE") && (splitted.size() > 1))
ZoomMode = std::stod(splitted[1]);
if ((toUpper(splitted[0]) == "ZOOMOFFSETX") && (splitted.size() > 1))
zoomOffsetX = std::stod(splitted[1]);
if ((toUpper(splitted[0]) == "ZOOMOFFSETY") && (splitted.size() > 1))
zoomOffsetY = std::stod(splitted[1]);
if ((toUpper(splitted[0]) == "GRAYSCALE") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
ImageGrayscale = true;
else if (toUpper(splitted[1]) == "FALSE")
ImageGrayscale = false;
}
if ((toUpper(splitted[0]) == "NEGATIVE") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
ImageNegative = true;
else if (toUpper(splitted[1]) == "FALSE")
ImageNegative = false;
}
if ((toUpper(splitted[0]) == "AEC2") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
ImageAec2 = true;
else if (toUpper(splitted[1]) == "FALSE")
ImageAec2 = false;
}
if ((toUpper(splitted[0]) == "AUTOEXPOSURELEVEL") && (splitted.size() > 1))
_autoExposureLevel = std::stod(splitted[1]);

if ((toUpper(splitted[0]) == "IMAGESIZE") && (splitted.size() > 1))
{
ImageSize = Camera.TextToFramesize(splitted[1].c_str());
Expand Down Expand Up @@ -129,6 +179,11 @@ bool ClassFlowTakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
_saturation = stoi(splitted[1]);
}

if ((toUpper(splitted[0]) == "SHARPNESS") && (splitted.size() > 1))
{
_sharpness = stoi(splitted[1]);
}

if ((toUpper(splitted[0]) == "FIXEDEXPOSURE") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
Expand All @@ -150,8 +205,8 @@ bool ClassFlowTakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
}
}

Camera.SetBrightnessContrastSaturation(_brightness, _contrast, _saturation);
Camera.SetQualitySize(ImageQuality, ImageSize);
Camera.SetBrightnessContrastSaturation(_brightness, _contrast, _saturation, _autoExposureLevel, ImageGrayscale, ImageNegative, ImageAec2, _sharpness);
Camera.SetQualitySize(ImageQuality, ImageSize, ZoomEnabled, ZoomMode, zoomOffsetX, zoomOffsetY);

image_width = Camera.image_width;
image_height = Camera.image_height;
Expand Down
7 changes: 7 additions & 0 deletions code/components/jomjol_flowcontroll/ClassFlowTakeImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ class ClassFlowTakeImage :
float waitbeforepicture_store;
framesize_t ImageSize;
bool isImageSize;
bool ZoomEnabled = false;
int ZoomMode = 0;
int zoomOffsetX = 0;
int zoomOffsetY = 0;
bool ImageGrayscale;
bool ImageNegative;
bool ImageAec2;
int ImageQuality;
time_t TimeImageTaken;
string namerawimage;
Expand Down
Loading