Skip to content
This repository has been archived by the owner on Mar 5, 2024. It is now read-only.

Commit

Permalink
Add PlaneAverage filter
Browse files Browse the repository at this point in the history
  • Loading branch information
dnjulek committed Jul 29, 2022
1 parent b91b1b9 commit 7ed0b13
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 99 deletions.
25 changes: 21 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
## PlaneStatsMod

Vapoursynth PlaneStats with threshold.\
Min and Max with threshold are useful for white balance scripts [like retinex](https://github.com/dnjulek/jvsfunc/blob/d3e41d9417f63b450b84e45e945d0402e33ff92e/jvsfunc/misc.py#L53).
Min and Max with threshold are useful for white balance scripts [like retinex](https://github.com/dnjulek/jvsfunc/blob/f7e1cad6f8cebeb011f8e6ee1d618526217da267/jvsfunc/misc.py#L53).

## PlaneMinMax

### Usage
```python
psm.PlaneStatsMod(vnode clip[, float minthr=0, float maxthr=0, int plane=0])
psm.PlaneMinMax(vnode clip [, float minthr=0, float maxthr=0, int plane=0])
```
### Parameters:

Expand All @@ -18,5 +18,22 @@ psm.PlaneStatsMod(vnode clip[, float minthr=0, float maxthr=0, int plane=0])
- maxthr\
Amount of the largest pixels dropped before pick the PlaneStatsMax.\
Should be a float between 0.0 and 1.0
- plane\
Plane to be used.


## PlaneAverage

### Usage
```python
psm.PlaneAverage(vnode clip, int[] value_exclude [, int plane=0])
```
### Parameters:

- clip\
A clip to process.\
Gets frame prop named ``psmAvg``.
- value_exclude\
List of pixel values that will be ignored during averaging.
- plane\
Plane to be used.
7 changes: 6 additions & 1 deletion msvc_project/PlaneStatsMod.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\PlaneStatsMod.cpp" />
<ClCompile Include="..\src\PlaneAverage.cpp" />
<ClCompile Include="..\src\PlaneMinMax.cpp" />
<ClCompile Include="..\src\shared.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\shared.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
Expand Down
13 changes: 12 additions & 1 deletion msvc_project/PlaneStatsMod.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,19 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\PlaneStatsMod.cpp">
<ClCompile Include="..\src\PlaneMinMax.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\shared.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\PlaneAverage.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\shared.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
126 changes: 126 additions & 0 deletions src/PlaneAverage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include "shared.h"

struct planeAverageData final {
VSNode* node;
const VSVideoInfo* vi;
std::vector<int> pxlist;
int plane;
};


static const VSFrame* VS_CC planeAverageGetFrame(int n, int activationReason, void* instanceData, void** frameData, VSFrameContext* frameCtx, VSCore* core, const VSAPI* vsapi) {
auto d{ static_cast<planeAverageData*>(instanceData) };

if (activationReason == arInitial) {
vsapi->requestFrameFilter(n, d->node, frameCtx);
}
else if (activationReason == arAllFramesReady) {
const VSFrame* src = vsapi->getFrameFilter(n, d->node, frameCtx);
VSFrame* dst = vsapi->copyFrame(src, core);
VSMap* dstProps = vsapi->getFramePropertiesRW(dst);
int height = vsapi->getFrameHeight(src, d->plane);
int width = vsapi->getFrameWidth(src, d->plane);
auto srcp = vsapi->getReadPtr(src, d->plane);
ptrdiff_t stride = vsapi->getStride(src, d->plane);
auto total = (int64_t)height * width;
double avg = 0.0;
uint64_t sum = 0;
double sumf = 0.0;

switch (d->vi->format.bytesPerSample) {
case 1:
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
auto pixel = srcp[x];
auto result = std::find(begin(d->pxlist), end(d->pxlist), pixel);
auto bresult = (result != std::end(d->pxlist));
if (!bresult) {
sum += pixel;
}

if (bresult) {
total--;
}
}
srcp += stride;
}
avg = (double)sum / (total * (((int64_t)1 << d->vi->format.bitsPerSample) - 1));
break;
case 2:
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
auto pixel = ((const uint16_t*)srcp)[x];
auto result = std::find(begin(d->pxlist), end(d->pxlist), pixel);
auto bresult = (result != std::end(d->pxlist));
if (!bresult) {
sum += pixel;
}

if (bresult) {
total--;
}
}
srcp += stride;
}
avg = (double)sum / (total * (((int64_t)1 << d->vi->format.bitsPerSample) - 1));
break;
case 4:
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
auto pixel = ((const float*)srcp)[x];
auto result = std::find(begin(d->pxlist), end(d->pxlist), pixel);
auto bresult = (result != std::end(d->pxlist));
if (!bresult) {
sumf += pixel;
}

if (bresult) {
total--;
}
}
srcp += stride;
}
avg = sumf / total;
break;
}

vsapi->mapSetFloat(dstProps, "psmAvg", avg, maReplace);
vsapi->freeFrame(src);
return dst;
}
return nullptr;
}

static void VS_CC planeAverageFree(void* instanceData, VSCore* core, const VSAPI* vsapi) {
auto d{ static_cast<planeAverageData*>(instanceData) };
vsapi->freeNode(d->node);
delete d;
}

void VS_CC planeAverageCreate(const VSMap* in, VSMap* out, void* userData, VSCore* core, const VSAPI* vsapi) {
auto d{ std::make_unique<planeAverageData>() };
int err = 0;

d->node = vsapi->mapGetNode(in, "clip", 0, nullptr);
d->vi = vsapi->getVideoInfo(d->node);

int numpx = vsapi->mapNumElements(in, "value_exclude");

for (int i = 0; i < numpx; i++) {
d->pxlist.push_back(vsapi->mapGetIntSaturated(in, "value_exclude", i, 0));
}

d->plane = vsapi->mapGetIntSaturated(in, "plane", 0, &err);
if (err)
d->plane = 0;

if (d->plane < 0 || d->plane >= d->vi->format.numPlanes) {
vsapi->mapSetError(out, "PlaneAverage: invalid plane specified");
vsapi->freeNode(d->node);
return;
}

VSFilterDependency deps[] = { {d->node, rpStrictSpatial} };
vsapi->createVideoFilter(out, "PlaneAverage", d->vi, planeAverageGetFrame, planeAverageFree, fmParallel, deps, 1, d.get(), core);
d.release();
}
Loading

0 comments on commit 7ed0b13

Please sign in to comment.