Image manipulation with Mathematica - linux

I've created this theme after my previous post. I can't run the following code (written by #belisarius):
a = Image["path/file.png"]
b = Image#ArrayPad[ImageData#a, {{40, 0}, {40}, {0}}, {1, 1, 1}];
f[image_, angleMult_] := ImageForwardTransformation[image, (
fi = ArcTan[Abs[#[[2]]/(#[[1]] - .5)]];
fi1 = angleMult fi (#[[1]]^2 + #[[2]]^2)/2;
{(1/2 - Sin[fi1] #[[2]] - Cos[fi1]/2 +
Cos[fi1] #[[1]]), -Sin[fi1]/2 + Sin[fi1] #[[1]] +
Cos[fi1] #[[2]]}) &]
t = Table[f[b, x], {x, 0, .2, .02}];
t1 = Reverse#t;
Export["anim.gif", Join[t, t1], "DisplayDurations" -> .15];
Import["anim.gif", "Animation"]
Here is a list of errors:
ArrayPad::depth: Padding amount {{40,0},{40},{0}} should specify padding in no more than the number of dimensions in array {{1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,0.996078,0.984314,<<142>>},<<49>>,<<145>>}. >>
Image::imgarray: The specified argument ArrayPad[{{1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,0.996078,0.984314,<<142>>},<<49>>,<<145>>},{{40,0},{40},{0}},{1,1,1}] should be an array of rank 2 or 3 with machine-sized numbers. >>
ImageForwardTransformation::imginv: Expecting an image or graphics instead of Image[ArrayPad[{{1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,0.996078,0.984314,<<142>>},<<49>>,<<145>>},{<<1>>},{1,1,1}]]. >>
General::stop: Further output of ImageForwardTransformation::imginv will be suppressed during this calculation. >>
Rasterize::bigraster: Not enough memory available to rasterize ImageForwardTransformation expression. >>
General::stop: Further output of Rasterize::bigraster will be suppressed during this calculation. >>
I'm using Mathematica 8 under Linux.

I think I got it.
The code above is for color images (3 channels) and it seems you are trying to run it over a B&W image (1 channel).
Either use a color image or replace the second line by:
b = Image#ArrayPad[ImageData#a, {{40, 0}, {40}}, 1];
Here is the result for your image using the above replacement as:
a = Binarize[Image["path/file.png"]]
b = Image#ArrayPad[ImageData#a, {{40, 0}, {40}}, 1];

Related

Programmatically Lighten or Darken a hex color in lua - nvim highlight colors

The goal is to programmatically change a hex colors brightness in lua.
This post contains several nice examples for js: Programmatically Lighten or Darken a hex color (or rgb, and blend colors)
I tried my luck to convert one of these functions, but I'm still pretty new to lua programming. It just needs to work with hex values, rgb or other variants are not needed. Therefore, I thought the "simpler" answers could serve as inspiration, but I still had no luck with it.
Eventually it shall be used to manipulate highlight colors in nvim. I'm getting the colorcodes with a function I wrote:
local function get_color(synID, what)
local command = 'echo synIDattr(hlID("' .. synID .. '"),' .. '"' .. what .. '"' .. ')'
return vim.api.nvim_command_output(command)
end
I wouldn't resort to bit ops in Lua 5.2 and lower, especially as Lua 5.1 lacks them (LuaJIT however does provide them); use multiplication, floor division & mod instead, and take care to clamp your values:
local function clamp(component)
return math.min(math.max(component, 0), 255)
end
function LightenDarkenColor(col, amt)
local num = tonumber(col, 16)
local r = math.floor(num / 0x10000) + amt
local g = (math.floor(num / 0x100) % 0x100) + amt
local b = (num % 0x100) + amt
return string.format("%#x", clamp(r) * 0x10000 + clamp(g) * 0x100 + clamp(b))
end
Especially with the introduction of bit operators in 5.3, the Javascript references work with minimal changes:
function LightenDarkenColor(col, amt)
col = tonumber(col, 16)
return string.format("%#x", ((col & 0x0000FF) + amt) | ((((col >> 8) & 0x00FF) + amt) << 8) | (((col >> 16) + amt) << 16))
end
print(LightenDarkenColor("3F6D2A", 40))
parseInt became tonumber and toString(16) string.format("%#x", ...)
Note that this function does not perform any error handling on overflows.
The second function on the linked page can be ported the same way. var would be a local in Lua.
For Lua 5.2 and below, you need to use the bit functions. I ported the second function instead, since it would get very unreadable very quickly:
function LightenDarkenColor(col, amt)
local num = tonumber(col, 16)
local r = bit.rshift(num, 16) + amt
local b = bit.band(bit.rshift(num, 8), 0x00FF) + amt
local g = bit.band(num, 0x0000FF) + amt
local newColor = bit.bor(g, bit.bor(bit.lshift(b, 8), bit.lshift(r, 16)))
return string.format("%#x", newColor)
end

How do I keep the original shape of the destination surface when blitting?

Take a look at the screenshot below. There are three thin SDL 2.0 surfaces displayed, all more or less rectangular.
Blitting image 1 onto image 2 - get image 3
The first surface (the brownish paper one) is Image 1
The white one below it with the two corners missing is Image 2
I would like to perform a SDL_BlitSurface so that Image 1 is blitted onto Image 2, but with the shape of Image 2 (in other words, the end result should look like brown paper, but have two of its corners missing.
To do this, I try:
SDL_BlitSurface(Image1, NULL, Image2, NULL);
But instead of the desired result, I get the third surface in the picture (Image 3), which is the same as Image 1
UPDATE
So on keltar's advice, I've replaced my blit function call with a call to a bespoke function that I hope is copying the alpha channel for each pixel from Image 1 to Image 2
copy_alpha(Image1, Image2);
void IMAGETOOL::copy_alpha(SDL_Surface * src, SDL_Surface * dst)
{
int w = src->w,
h = src->h;
Uint32 opixel, npixel;
Uint8 r, g, b, a;
if (SDL_MUSTLOCK(src)) SDL_LockSurface(src);
if (SDL_MUSTLOCK(dst)) SDL_LockSurface(dst);
Uint8 srcAlpha = 0;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
{
opixel = get_pixel(src, x, y);
SDL_GetRGBA(opixel, src->format, &r, &g, &b, &a);
srcAlpha = a;
opixel = get_pixel(dst, x, y);
SDL_GetRGBA(opixel, dst->format, &r, &g, &b, &a);
a = srcAlpha;
npixel = SDL_MapRGBA(dst->format, r, g, b, a);
put_pixel(dst, x, y, npixel);
}
if (SDL_MUSTLOCK(src)) SDL_UnlockSurface(src);
if (SDL_MUSTLOCK(dst)) SDL_UnlockSurface(dst);
}
The resulting surface has changed. but not in the way I had hoped.
Copying alpha from image 1 to image 2 - get image 3
Not sure what to make of this - any ideas?
Problem solved. In my last update, I was trying to copy alpha from Image 1 to Image 2 - wrong way round!
But when I use the same function to copy alpha from image 2 to Image 1 (I'm guessing that is what keltar meant for me to do).
copy_alpha(Image2, Image1);
the modified Image 1 gives the desired result.
Copying alpha from image 2 to image 1 - get image 3
Thanks for your help keltar!

V4L2_PIX_FMT_YUYV: convert from YUYV to RGB24?

I'm capturing image data from a webcam using Video4Linux2. The pixel format returned by the device is V4L2_PIX_FMT_YUYV. According to http://linuxtv.org/downloads/v4l-dvb-apis/V4L2-PIX-FMT-YUYV.html this is the same as YUV422 so I used a YUV422 to RGB24 conversion based on the description at http://paulbourke.net/dataformats/yuv/ .
Amazingly the result is a strange violet/green picture. So it seems YUYV is something different than YUV422 (and there also exists a pixel format V4L2_PIX_FMT_YUV422P which is/is not the same?).
So I'm totally confused now: how can I convert a V4L2_PIX_FMT_YUYV bitmap to real RGB24? Are there any examples out there?
Too long to put in a comment...
4:2:2 is not a pixel-format, it is just a notation about how the chroma-data have been subsampled. According to the linuxtv-link, V4L2_PIX_FMT_YUYV is identical to YUYV or YUY2.
The ultimate reference on the subject is http://www.fourcc.org. Have a look at what it says about YUY2 at http://www.fourcc.org/yuv.php#YUYV
Horizontal Vertical
Y Sample Period 1 1
V Sample Period 2 1
U Sample Period 2 1
To verify that that the input format indeed is YUYV you can use a viewer I wrote using SDL; which natively supports this format (among others)
https://github.com/figgis/yuv-viewer
See also http://www.fourcc.org/fccyvrgb.php for correct formulas for rgb/yuv-conversion.
Take it from there and drop me a comment if you need further assistance...
I had a similar problem and the issue was endianness. V4L returns pixel data as a series of bytes which I was casting to 16 bit ints. Because of the endianness of my machine the Y and Cb (or Y and Cr for odd pixels) values were getting swapped and I was getting a weird violet/green image.
The solution was just to change how I was extracting Y, Cb and Cr from my 16 bit ints. That is to say, instead of this:
int y = pixbuf[i] & 0xFF00) >> 8;
int u = pixbuf[(i / 2) * 2] & 0xFF;
int v = pixbuf[(i / 2) * 2 + 1] & 0xFF;
I should have done this:
int y = (pixbuf[i] & 0xFF);
int u = (pixbuf[(i / 2) * 2] & 0xFF00) >> 8;
int v = (pixbuf[(i / 2) * 2 + 1] & 0xFF00) >> 8;
Or indeed just processed them as a sequence of bytes like a sensible person...

cvIntegral for determining sum of 4X4 blocks

I'd like to sum my 4X4 block. Suppose I have an image and will divide it into 4X4 blocks. Then afterward I'd like to determine the sum of each block using cvIntegral. How can I cope this?
Here is my basic program in order to calculate integral image value of whole image:
float s = 0.0f;
//Read in the image
IplImage* hImage = cvLoadImage("bayer-image.jpg",0);
UINT width = hImage->width; UINT height = hImage->height;
CvMat* sum = cvCreateMat(height + 1, width + 1, CV_32SC1);
CvMat* sqsum = cvCreateMat(height + 1, width + 1, CV_64FC1);
cvIntegral(hImage, sum, sqsum);
cvReleaseImage(&hImage);
cvReleaseMat(&sum);
cvReleaseMat(&sqsum);
What should I do next?
Really thanks in advance.
Check this out
http://en.wikipedia.org/wiki/Summed_area_table
As an example, the block defined by the corners (1, 1) and (4, 4) has the area
a1 = integral(0,0)+integral(4,4)-integral(4,0)-integral(0,4);

Replacing Disks by Crosses using Graphics in Mathematica

Consider the following list :
dalist = {{47.9913, 11.127, 208}, {47.5212, 10.3002, 208},
{49.7695, 9.96838, 160}, {48.625, 12.7042, 436}}
Those are coordinatees of Eye fixations on a screen where, within each sublist,
#1 is the X coordinate,
#2 the Y coordinate and
#3, the duration spent at that particular location
I then use the following :
Disk[{#[[1]], #[[2]]}, 3N[#[[3]]/Total[dalist[[All, 3]]]]] & /# dalist
to draw disk with duration weighted diameter.
I would like to draw cross instead where the 2 segments intersect at their middle and the length of each is equivalent to the disk diameter as illustrated bellow.
This is what I have yet :
Graphics[{
Line[{{#[[1]] - 3 N[#[[3]]/Total[dalist[[All, 3]]]], #[[2]]},
{#[[1]] + 3 N[#[[3]]/Total[dalist[[All, 3]]]], #[[2]]}}] & /# dalist,
Line[{{#[[1]], #[[2]] - 3 N[#[[3]]/Total[dalist[[All, 3]]]]},
{#[[1]], #[[2]] + 3 N[#[[3]]/Total[dalist[[All, 3]]]]}}] & /# dalist}]
I was wondering if there was a simpler way, using something similar to PlotMarkers that exist in ListPlot
Use two lines. Something like:
pointTrans =
{
Line[{{#[[1]] - l, #[[2]]}, {#[[1]] + l, #[[2]]}}],
Line[{{#[[1]], #[[2]] - l}, {#[[1]], #[[2]] + l}}]
} /. l -> #[[3]]/Mean[dalist[[All, 3]]] &;
pointTrans /# dalist // Graphics // Show
As you can already draw the circles, why not just use that like so:
circles=Graphics[Disk[{#[[1]], #[[2]]}, 3 N[#[[3]]/Total[dalist[[All, 3]]]]] & /# dalist]
and then
circles /. Disk[{x_, y_}, r_] :> Line[{{{x, y - r/2}, {x, y + r/2}}, {{x - r/2, y}, {x + r/2, y}}}]
giving
I think a little helper function is convenient here:
makeCross[{x_, y_, r_}, total_] := With[{scale = 3*r/total},
Line[{{{x - scale, y}, {x + scale, y}}, {{x, y - scale}, {x, y + scale}}}]]
total = Total[dalist[[All, 3]]];
Graphics[makeCross[#, mean] & /# dalist]
You could also use BubbleChart:
plus[{x:{x0_, x1_}, y:{y0_, y1_}}, __] :=
Line[{{{x0, Mean[y]}, {x1, Mean[y]}}, {{Mean[x], y0}, {Mean[x], y1}}}]
BubbleChart[dalist, ChartElementFunction -> plus] (*or maybe "MarkerBubble" instead of plus*)
I would like to offer this modification of Artefacto's code.
pointTrans =
With[{l = #3/2/Mean#dalist[[All, 3]]},
Line#{{{# - l, #2}, {# + l, #2}}, {{#, #2 - l}, {#, #2 + l}}}
] &;
Graphics[{Thick, pointTrans ### dalist}]

Resources