How would I find the mode (stats) of pixel values of an image? - opencv

I'm using opencv and I'm able to get a pixel of an image-- a 3-dimensional tuple, via the code below. However, I'm not quite sure how to calculate the mode of the pixels values in the image.
import cv2
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
import cv2
img =cv2.imread('C:\\Users\Moondra\ABEO.png')
#px = img[100,100] #gets pixel value
#print (px)
I tried,
from scipy import stats
stats.mode(img)[0]
But this returns an array shape of
stats.mode(img)[0].shape
(1, 800, 3)
Not sure how exactly stats is calculating the dimensions from which to choose the mode, but I'm looking for each pixel value (3 dimensional tuple) to be one element.
EDIT:
For clarity, I'm going to lay out exactly what I'm looking for.
Let's say we have an array that is of shape (3,5,3) and looks like this
array([[[1, 1, 2], #[1,1,2] = represents the RGB values
[2, 2, 2],
[1, 2, 2],
[2, 1, 1],
[1, 2, 2]],
[[1, 2, 2],
[2, 2, 2],
[2, 2, 2],
[1, 2, 2],
[1, 2, 1]],
[[2, 2, 1],
[2, 2, 1],
[1, 1, 2],
[2, 1, 2],
[1, 1, 2]]])
I would then convert it to an array that looks like this for easier calculation
Turn this into
array([[1, 1, 2],
[2, 2, 2],
[1, 2, 2],
[2, 1, 1],
[1, 2, 2],
[1, 2, 2],
[2, 2, 2],
[2, 2, 2],
[1, 2, 2],
[1, 2, 1],
[2, 2, 1],
[2, 2, 1],
[1, 1, 2],
[2, 1, 2],
[1, 1, 2]])
which is of shape(15,3)
I would like to calculate the mode by counting each set of RGB as follows:
[1,1,2] = 3
[2,2,2] = 4
[1,2,2] = 4
[2,1,1] = 2
[1,1,2] =1
Thank you.

From the description, it seems you are after the pixel that's occurring the most in the input image. To solve for the same, here's one efficient approach using the concept of views -
def get_row_view(a):
void_dt = np.dtype((np.void, a.dtype.itemsize * np.prod(a.shape[-1])))
a = np.ascontiguousarray(a)
return a.reshape(-1, a.shape[-1]).view(void_dt).ravel()
def get_mode(img):
unq, idx, count = np.unique(get_row_view(img), return_index=1, return_counts=1)
return img.reshape(-1,img.shape[-1])[idx[count.argmax()]]
We can also make use of np.unique with its axis argument, like so -
def get_mode(img):
unq,count = np.unique(img.reshape(-1,img.shape[-1]), axis=0, return_counts=True)
return unq[count.argmax()]
Sample run -
In [69]: img = np.random.randint(0,255,(4,5,3))
In [70]: img.reshape(-1,3)[np.random.choice(20,10,replace=0)] = 120
In [71]: img
Out[71]:
array([[[120, 120, 120],
[ 79, 105, 218],
[ 16, 55, 239],
[120, 120, 120],
[239, 95, 209]],
[[241, 18, 221],
[202, 185, 142],
[ 7, 47, 161],
[120, 120, 120],
[120, 120, 120]],
[[120, 120, 120],
[ 62, 41, 157],
[120, 120, 120],
[120, 120, 120],
[120, 120, 120]],
[[120, 120, 120],
[ 0, 107, 34],
[ 9, 83, 183],
[120, 120, 120],
[ 43, 121, 154]]])
In [74]: get_mode(img)
Out[74]: array([120, 120, 120])

Related

dart generating all possible combinations list of lists

I have a list of lists, similar to this:
a = [ [1,2,3], [4,5,6], [7,8,9,10]]
I'd like to create all possible combinations, like this:
[(1, 4, 7), (1, 4, 8), (1, 4, 9), (1, 4, 10), (1, 5, 7), (1, 5, 8), (1, 5, 9), (1, 5, 10), (1, 6, 7), (1, 6, 8), (1, 6, 9), (1, 6, 10), (2, 4, 7), (2, 4, 8), (2, 4, 9), (2, 4, 10), (2, 5, 7), (2, 5, 8), (2, 5, 9), (2, 5, 10), (2, 6, 7), (2, 6, 8), (2, 6, 9), (2, 6, 10), (3, 4, 7), (3, 4, 8), (3, 4, 9), (3, 4, 10), (3, 5, 7), (3, 5, 8), (3, 5, 9), (3, 5, 10), (3, 6, 7), (3, 6, 8), (3, 6, 9), (3, 6, 10)]
For python, there's a library that does exactly this.
Is there a similar solution for Dart?
If not, I'd appreciate a simple code that accomplish that
One approach could be:
Iterable<List<T>> allCombinations<T>(List<List<T>> sources) sync* {
if (sources.isEmpty || sources.any((l) => l.isEmpty)) {
yield [];
return;
}
var indices = List<int>.filled(sources.length, 0);
var next = 0;
while (true) {
yield [for (var i = 0; i < indices.length; i++) sources[i][indices[i]]];
while (true) {
var nextIndex = indices[next] + 1;
if (nextIndex < sources[next].length) {
indices[next] = nextIndex;
break;
}
next += 1;
if (next == sources.length) return;
}
indices.fillRange(0, next, 0);
next = 0;
}
}
This works by effectively treating the indices as a number in variable base based on the source list lengths, then incrementing it and creating the corresponding list.
Time complexity is still 𝒪(Πi(source[i].length) * source.length).
Could not find a package which does exactly what you want, but I guess your can do something like this if you want to introduce your own method:
void main() {
print(combinations([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9, 10]
]));
// ([1, 4, 7], [1, 4, 8], [1, 4, 9], [1, 4, 10], ..., [3, 6, 9], [3, 6, 10])
}
Iterable<List<T>> combinations<T>(
List<List<T>> lists, [
int index = 0,
List<T>? prefix,
]) sync* {
prefix ??= <T>[];
if (lists.length == index) {
yield prefix.toList();
} else {
for (final value in lists[index]) {
yield* combinations(lists, index + 1, prefix..add(value));
prefix.removeLast();
}
}
}
More efficient solution but also more risky to use since it does require the user of combinations to take care when consuming the output and make sure not to keep any instances of the inner Iterable:
void main() {
print(combinations([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9, 10]
]).map((e) => e.toList()));
// ([1, 4, 7], [1, 4, 8], [1, 4, 9], [1, 4, 10], ..., [3, 6, 9], [3, 6, 10])
}
Iterable<Iterable<T>> combinations<T>(
List<List<T>> lists, [
int index = 0,
List<T>? prefix,
]) sync* {
prefix ??= <T>[];
if (lists.length == index) {
yield prefix;
} else {
for (final value in lists[index]) {
yield* combinations(lists, index + 1, prefix..add(value));
prefix.removeLast();
}
}
}
The problem with this solution is the risk of misuse as the following example:
final listOfCombinations = combinations([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9, 10]
]).toList();
print(listOfCombinations);
// [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]
Which should instead be:
final listOfCombinations = combinations([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9, 10]
]).map((e) => e.toList()).toList();
print(listOfCombinations);
// [[1, 4, 7], [1, 4, 8], [1, 4, 9], [1, 4, 10], [1, 5, 7], [1, 5, 8], [1, 5, 9], [1, 5, 10], [1, 6, 7], [1, 6, 8], [1, 6, 9], [1, 6, 10], [2, 4, 7], [2, 4, 8], [2, 4, 9], [2, 4, 10], [2, 5, 7], [2, 5, 8], [2, 5, 9], [2, 5, 10], [2, 6, 7], [2, 6, 8], [2, 6, 9], [2, 6, 10], [3, 4, 7], [3, 4, 8], [3, 4, 9], [3, 4, 10], [3, 5, 7], [3, 5, 8], [3, 5, 9], [3, 5, 10], [3, 6, 7], [3, 6, 8], [3, 6, 9], [3, 6, 10]]
So, use the first suggested solution if you don't want the risk of this kind of issues. :)
check out this answer. working for the problem you are searching for:
https://stackoverflow.com/a/57883482/11789758

How to declare a jagged array in Dart

I have been googling for 2 days now and I have not found how to create a jagged list(array) in Dart.
There is this Dart - How to initialize a jagged array? but the given answer makes a normal list(array), what i want is something like this:
Not sure I understand the question. But is it something like this where we create a list of lists where each list in the list has a different length?
void main() {
final arr = [
[10, 9, 8],
[7, 5, 6, 88],
[30, 15],
[90],
[10, 20, 30, 40, 50]
];
print(arr); // [[10, 9, 8], [7, 5, 6, 88], [30, 15], [90], [10, 20, 30, 40, 50]]
}

Can I use cvxpy to split integer-2D-array to two arrays?

I have a problem that I wonder if I can solve using cvxpy:
The problem:
I have a two dimensional integers array and I want to split it to two array in a way that each row of the source array is either in the 1st or 2nd array.
The requirement from these arrays us that for each column, the sum of integers in array #1 will be as close as possible to twice the sum of integers in array #2.
Example:
Consider the input array:
[
[1, 2, 3, 4],
[4, 6, 2, 5],
[3, 9, 1, 2],
[8, 1, 0, 9],
[8, 4, 0, 5],
[9, 8, 0, 4]
]
The sums of its columns is [33, 30, 6, 29] so ideally we are looking for 2 arrays that the sums of their columns will be:
Array #1: [22, 20, 4, 19]
Array #2: [11, 10, 2, 10]
Off course this is not always possible but I looking for the best solution for this problem.
A possible solution for this specific example might be:
Array #1:
[
[1, 2, 3, 4],
[4, 6, 2, 5],
[8, 4, 0, 5],
[9, 8, 0, 4]
]
With column sums: [22, 20, 5, 18]
Array #2:
[
[3, 9, 1, 2],
[8, 1, 0, 9],
]
With column sums: [11, 10, 1, 11]
Any suggestions?
You can use a boolean vector variable to select rows. The only thing left to decide is how much to penalize errors. In this case I just used the norm of the difference vector.
import cvxpy as cp
import numpy as np
data = np.array([
[1, 2, 3, 4],
[4, 6, 2, 5],
[3, 9, 1, 2],
[8, 1, 0, 9],
[8, 4, 0, 5],
[9, 8, 0, 4]
])
x = cp.Variable(data.shape[0], boolean=True)
prob = cp.Problem(cp.Minimize(cp.norm((x - 2 * (1 - x)) * data)))
prob.solve()
A = np.round(x.value) # data
B = np.round(1 - x.value) # data
A and B are the sum of rows.
(array([21., 20., 4., 19.]), array([12., 10., 2., 10.]))

How to sort map's values?

Can someone give me a hint? I want to sort a map's values by the length of the lists.
var chordtypes = {
"maj": [0, 4, 7],
"M7": [0, 4, 7, 11],
"m7": [0, 3, 7, 10],
"6": [0, 4, 7, 9],
"9": [0, 4, 7, 10, 14],
"sus2": [0, 2, 7],
"sus4": [0, 5, 7],
"omit3": [0, 7],
"#5": [0, 4, 8],
"+7b9#11": [0, 4, 8, 10, 13, 18],
"+9": [0, 4, 8, 10, 14]
};
A function that does sort a Map of List on their length.
import 'dart:collection';
/// sorts the ListMap (== A Map of List<V>) on the length
/// of the List values.
LinkedHashMap sortListMap(LinkedHashMap map) {
List mapKeys = map.keys.toList(growable : false);
mapKeys.sort((k1, k2) => map[k1].length - map[k2].length);
LinkedHashMap resMap = new LinkedHashMap();
mapKeys.forEach((k1) { resMap[k1] = map[k1] ; }) ;
return resMap;
}
result for :
var res = sortListMap(chordtypes);
print(res);
==>
{ omit3: [0, 7],
maj: [0, 4, 7],
sus2: [0, 2, 7],
sus4: [0, 5, 7],
#5: [0, 4, 8],
M7: [0, 4, 7, 11],
m7: [0, 3, 7, 10],
6: [0, 4, 7, 9],
9: [0, 4, 7, 10, 14],
+9: [0, 4, 8, 10, 14],
+7b9#11: [0, 4, 8, 10, 13, 18] }
Using DART language:
Let's say you want to sort a Map with integer key and value of type Foo:
class Foo {
int x; //it can be any type
}
So you can get the list of all the entries, sort them like a normal list and then rebuild the map:
Map<int, Foo> map = //fill map
var entries = map.entries.toList();
entries.sort((MapEntry<int, Foo> a, MapEntry<int, Foo> b) => a.value.x.compareTo(b.value.x));
map = Map<int, Foo>.fromEntries(entries);
Something like this could work for you:
Map chordtypes = {
"maj": [0, 4, 7],
"M7": [0, 4, 7, 11],
"m7": [0, 3, 7, 10],
"6": [0, 4, 7, 9],
"9": [0, 4, 7, 10, 14],
"sus2": [0, 2, 7],
"sus4": [0, 5, 7],
"omit3": [0, 7],
"#5": [0, 4, 8],
"+7b9#11": [0, 4, 8, 10, 13, 18],
"+9": [0, 4, 8, 10, 14]
};
List keys = chordtypes.keys.toList();
keys.sort((k1, k2) {
if(chordtypes[k1].length > chordtypes[k2].length)
return -1;
if(chordtypes[k1].length < chordtypes[k2].length)
return 1;
return 0;
});
keys.forEach((String k) {
print('$k ${chordtypes[k]}');
});
Building on #Leonardo Rignanese's answer. An extension function for a more functional approach:
extension MapExt<T, U> on Map<T, U> {
Map<T, U> sortedBy(Comparable value(U u)) {
final entries = this.entries.toList();
entries.sort((a, b) => value(a.value).compareTo(value(b.value)));
return Map<T, U>.fromEntries(entries);
}
}
General usage:
foos.sortedBy((it) => it.bar);
Usage for OP:
final sortedChordtypes = chordtypes.sortedBy((it) => it.length);
Gist here: https://gist.github.com/nmwilk/68ae0424e848b9f05a8239db6b708390

ruby array iteration

I have four arrays(named array1,2,3,4) each with 8 objects and want to sort them into 8 empty arrays that will consist of 4 objects each, i.e place each object from array 1 into an empty array.
?? << array1.shift until array.empty?
I'm not sure how to iterate over the 8 empty arrays so that each of them recieves an object from array1
e.g
array1 = clubs1-8
array2 = spades1-8
array3 = hearts1-8
array4 = diamonds1-8
8 empty arrays or players, each player is dealt a card from array1,then 1 card from array2 etc.
Thanks for the answers but I wanted to add the objects iteratively so I could add conditions based on what objects had already been added to each array
e.g
distribute array1 among 8 empty arrays
distribute array2 among the 8 arrays but check before that no array contains the same card number (it can't have both the 2 of hearts and the 2 of diamonds)
Did you mean something like this?
require "matrix"
a1 = (0..7).to_a
a2 = (8..15).to_a
a3 = (16..23).to_a
a4 = (24..31).to_a
Matrix[a1, a2, a3, a4].transpose.to_a #=> [[0, 8, 16, 24], [1, 9, 17, 25], [2, 10, 18, 26], [3, 11, 19, 27], [4, 12, 20, 28], [5, 13, 21, 29], [6, 14, 22, 30], [7, 15, 23, 31]]
Added:
In fact it is even more trivial:
a1.zip(a2, a3, a4) #=> [[0, 8, 16, 24], [1, 9, 17, 25], [2, 10, 18, 26], [3, 11, 19, 27], [4, 12, 20, 28], [5, 13, 21, 29], [6, 14, 22, 30], [7, 15, 23, 31]]
Iteration is not the only way. Try this (assuming a1..a8 are your 8 empty arrays):
a1, a2, a3, a4, a5, a6, a7, a8 = array1.zip(array2, array3, array4)
irb(main):001:0> ar1 = [1,2,3,4,5,6,7,8]
=> [1, 2, 3, 4, 5, 6, 7, 8]
irb(main):002:0> ar2 = [2,3,4,1,2,3,2,1]
=> [2, 3, 4, 1, 2, 3, 2, 1]
irb(main):003:0> ar3 = [4,3,5,6,3,3,4,5]
=> [4, 3, 5, 6, 3, 3, 4, 5]
irb(main):004:0> ar4 = [5,2,5,6,7,2,2,5]
=> [5, 2, 5, 6, 7, 2, 2, 5]
irb(main):005:0> ar1.zip(ar2,ar3,ar4)
=> [[1, 2, 4, 5], [2, 3, 3, 2], [3, 4, 5, 5], [4, 1, 6, 6], [5, 2, 3, 7], [6, 3, 3, 2], [7, 2, 4, 2], [8, 1, 5, 5]]

Resources